? Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机制。在Java语言里面,类型的加载、连接和初始化过程都是在程序运行期间完成的。Java天生可以动态扩展的语言特性就是依赖运行期动态加载和动态连接这个特点实现的。
? 一般我们把类从加载到内存到卸载出内存的整个过程分为七个阶段:加载,验证,准备,解析,初始化,使用和卸载。其中,验证、准备和解析统称为连接。
? 在这几个阶段中,加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的,而解析阶段则不一定,它有时候可能会在初始化之后开始,这是为了支持Java的运行时绑定。需要特别注意的是,这里边的顺序指的是按顺序开始,而不是按顺序进行或完成,因为这些阶段通常会互相交叉的混合进行。
? 对于初始化阶段,《Java虚拟机规范》严格规定了有且只有6种情况必须对类进行”初始化“(而加载、验证、准备自然需要在此之前开始):
根类加载器(Bootstrap class Loader)
负责加载jdk核心类(rt.jar)
扩展类加载器(Extension Class Loader)
负责加载jdk中jre/lib/ext下的jar中的字节码文件
应用程序类加载器(Application Class Loader)
负责加载自定义类或classpath下第三方的jar中的类
自定义类加载器(User Class Loader)
通过继承ClassLoader类实现,主要重写findClass方法。
? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射(Reflection)机制。
List<Integer>
,越过泛型检测new User()
、new UserDto()
? 在JDK中,主要由以下类来实现Java反射机制,这些类(除了Class.java)都位于java.lang.reflect
包中
? Class类非常特殊,它没有公共构造方法,而是由JVM创建。Java中,无论生成某个类的多少个对象,这些对象都会对应同一个Class对象。这个Class是由JVM创建的,通过它能够获悉整个类的结构。
Class类中的静态方法forName()
Class<?> cls=Class.forName("com.sofwin.pojo.User"); //forName("全限定类名")
User u= (User) cls.newInstance();
使用类名.class
的方式
Class<String> c1=String.class;
Object类中的getClass()
方法
User user=new User();
Class<?> class1 = user.getClass();
User user2=(User) class1.newInstance();
System.out.println(user==user2);//false
获取类相关的方法
返回值类型 | 方法 | 描述 |
---|---|---|
Class<?> | forName(String className) | 根据全限定类名生成该类的类对象 |
Class<?>[] | getClasses() | 返回一个数组,包含该类中所有公共类和接口类的对象 |
ClassLoader | getClassLoader() | 返回该类的类加载器 |
String | getName() | 返回该类的全限定类名 |
Package | getPackage() | 获取该类的包 |
String | getSimpleName() | 获取类的名字 |
Class<? super T> | getSuperclass() | 获取当前类继承的父类的类对象 |
Class<?>[] | getInterfaces() | 获取当前类实现的所有接口的类对象 |
获取类中相关属性的方法
返回值类型 | 方法 | 描述 |
---|---|---|
Field[] | getFields() | 获取该类的所有公有属性对象,Field数组 |
Field | getField(String name) | 根据属性名获取该类中对应的公有属性对象,Field对象 |
Field[] | getDeclaredFields() | 获取该类所有属性的对象,Field数组 |
Field | getDeclaredField(String name) | 根据属性名获取该类中对应的属性对象,Field对象 |
获取类中构造器相关的方法
返回值类型 | 方法 | 描述 |
---|---|---|
Constructor<?>[] | getConstructors() | 获取该类中所有公有的构造方法对象,Constructor数组 |
Constructor<?> | getConstructor(Class...<?> paramterTypes ) | 根据参数获取该类中对应的公有构造器对象,Constructor对象 |
Constructor<?>[] | getDeclaredConstructor() | 获取该类中的所有构造方法对象数组,Constructor数组 |
Constructor<?> | getDeclaredConstructor(Class...<?> paramterTypes) | 根据参数获取该构造方法对象,Constructor对象 |
获取类中方法相关的方法
返回值类型 | 方法 | 描述 |
---|---|---|
Methods<?>[] | getMethods() | 获取该类中所有的公有方法对象的数组 |
Methods<?> | getMethod(String name,Class<?>...paeamterTypes) | 根据方法名获取类中对应的public方法对象 |
Methods<?>[] | getDeclaredMethods() | 获取该类中所有方法的对象数组 |
Methods<?> | getDeclaredMethod(String name.Class<?>...paramterTypes) | 根据方法名和参数获取该类中对应的方法对象 |
其它重要方法
返回值类型 | 方法 | 描述 |
---|---|---|
T | newInstance() | 根据类对象创建实例对象(类中必须有无参构造方法) |
返回值类型 | 方法 | 描述 |
---|---|---|
void | set(Object obj,Object value) | 给obj对象的当前属性设置value值 |
String | getName() | 获取当前字段的名称 |
int | getModifiers() | 获取当前字段的修饰符 |
void | setAccessible(boolean flag) | 设置暴力访问,可以访问私有属性 |
Object | get(Object obj) | 返回obj对象当前属性的值 |
返回值类型 | 方法 | 描述 |
---|---|---|
Object | invoke(Object obj,Object...args) | 根据类对象创建实例对象(类中必须有无参构造方法) |
void | setAccessible(boolean flag) | 可以暴力调用私有方法 |
Class<?>[] | getParamterTypes() | 获取方法的所有参数的类对象 |
Class<?> | getReturnType() | 获取方法的返回值对象 |
返回值类型 | 方法 | 描述 |
---|---|---|
T | newInstance(Object...initargs) | 调用有参构造反射生成对象 |
Class<?>[] | getParamterTypes() | 获取方法的所有参数的类对象 |
public class Test1 {
public static void main(String[] args) {
List<Integer> ids=new ArrayList<Integer>();
ids.add(1);
ids.add(2);
ids.add(3);
ids=Test1.getList(ids);
for (Integer id : ids) {
System.out.println(id);
}
}
private static List<Integer> getList(List<Integer> ids) {
//获取ids的类对象
Class clazz=ids.getClass();
//获取add()方法对象
try {
Method method = clazz.getDeclaredMethod("add", Object.class);
//暴力破解
method.setAccessible(true);
//反射调用该方法,放入字符串
method.invoke(ids, "test");
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ids;
}
}
public static <T> List<T> executeQuery(Class resultType,String sql,Object...objects){
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List result = new ArrayList();
try {
conn = JdbcUtil.getConnection();
pstmt = conn.prepareStatement(sql);
//处理占位符
for(int i=0;i<objects.length;i++) {
pstmt.setObject(i+1, objects[i]);
}
rs = pstmt.executeQuery();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
while(rs.next()) {
//每次循环生成对象
Object obj = resultType.newInstance();
//给未知的成员变量赋值(查询结果的列名就是我们的属性名称)
for(int i=0;i<columnCount;i++) {
//获取到查询结果的列名
String columnName = metaData.getColumnLabel(i+1);
Field field = resultType.getDeclaredField(columnName);
if(field!=null) {
field.setAccessible(true);
if(field.getType()==Integer.class) {
field.set(obj, Integer.parseInt(rs.getObject(columnName)==null?"0":rs.getObject(columnName).toS tring()));
}
if(field.getType()==Float.class) {
field.set(obj, Float.parseFloat(rs.getObject(columnName)==null?"0":rs.getObject(columnName).toS tring()));
}
if(field.getType()==Double.class) {
field.set(obj, Double.parseDouble(rs.getObject(columnName)==null?"0":rs.getObject(columnName).t oString()));
}
if(field.getType()==String.class) {
field.set(obj, rs.getObject(columnName)==null?"":rs.getObject(columnName).toString());
}
}
}
//将obj对象加入到result集合中
result.add(obj);
}
}catch(Exception ex) {
}finally {
JdbcUtil.closeAll(conn, pstmt, rs);
}
return result;
}
? 在Java中代理有两种方式:
JDK的动态代理只能代理接口或实现过接口的类的对象。
代理对象可以对目标对象的相关方法进行功能扩展(增强)
返回值 | 方法 | 描述 |
---|---|---|
static Object | newProxyInstance(ClassLoader loader, Class<?>[]interfaces, InvocationHandler h) | 生成目标对象的代理对象(目标对象必须实现过接口) |
public class Test7 {
public static void main(String[] args) throws NoSuchFieldException, SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException {
UserDao dao = new UserDaoImpl();//目标对象
/**
* newProxyInstance中的参数
* 参数1:类加载器
* 参数2:目标类中实现的接口的类对象数组
* 参数3:是代理实例的调用处理程序 实现的接口
* InvacationHandler接口的实例的
* 在代理对象中如何去执行目标对象的方法
*/
UserDao daoProxy= (UserDao)Proxy.newProxyInstance(Test7.class.getClassLoader(), dao.getClass().getInterfaces(), new InvocationHandler() {
/**
* 参数1:代理实例
* 参数2:被调用的方法
* 参数3:方法的参数
* 返回值:目标方法的返回值
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//反射调用目标方法
Object obj = method.invoke(dao, args);
return obj;
}
});
//调用目标对象的方法
dao.test();
daoProxy.test();
System.out.println(daoProxy instanceof UserDao);
}
}
public class UserDAOProxyFactory {
public static UserDAO createUserDAO() {
/**
* 类加载器:system classLoader
* 参数2:实例的代理对象----该实例实现过的接口的类对象的数组
* 接口的代理对象----该接口的类对象的数组
*/
UserDAO dao = (UserDAO)Proxy.newProxyInstance(UserDAO.class.getClassLoader(), new Class[] {UserDAO.class}, new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().contains("save")) {
System.out.println("saveUser......");
}
if(method.getName().contains("delete")) {
System.out.println("delete.......");
}
return null;
}
});
return dao;
}
}
原文:https://www.cnblogs.com/xxyang/p/13600269.html