Java回炉之反射(一)
类的加载
- 加载类的时机
- 创建实例
- 访问静态变量,或为静态变量赋值
- 调用静态方法
- 使用反射强制创建类或对应的Class对象
- 初始化其子类
- 使用java.exe运行的主类
- 将class文件读入内存,并为之创建一个Class对象。
- 验证内部结构
- 为静态成员分配内存,设置默认初始化值
- 将符号引用替换为直接引用
类加载器
- Bootstrap 引导类
- Extension 扩展类
- System 系统类
获取class文件
- new Demo().getClass()
- Demo.class
- Class.forName(“package.name.Demo”);
获取并使用构造方法
Class c=Class.forName("package.name.Demo");
c.getContructors();//获取公共构造方法
c.getDeclaredConstructors();//获取所有构造方法
Constructor con=c.getConstructor();//参数为对应构造方法的参数对应的Class对象
Constructor con=c.getConstructor(int.class);//获取带int参数的构造方法
Object obj =con.newInstance();//创建Demo实例
Object obj= com.newInstance(2);
con.setAccessible(boolean);//参数为true时可以访问private成员
获取并使用成员变量
Class c=Class.forName("package.name.Demo");
c.getFields();//获取公共成员变量
c.getDeclaredFields();//获取所有成员变量
Field f=c.getField(”“);//根据变量名获取字段
f.setAccessible(true);//设置强制访问
Field f=c.getDeclaredField(”“);//根据变量名获取private字段
f.set(new Demo(),"");//给demo的f字段设置值为""
获取并使用方法
Class c=Class.forName("package.name.Demo");
c.getMethods();//获取自己及父的类公共方法
c.getDeclaredMethods();//获取自己的所有方法
Method m=c.getMethod(String name,...);//第一个参数为要获取方法的方法名,后面的参数为要获取方法的参数类型列表
m.invoke(new Demo());//调用demo对象的m方法,第二个及其后参数将传递给m方法,返回值为m方法的返回值
通过反射躲避泛型检查
// 创建集合对象
ArrayList<Integer> array = new ArrayList<Integer>();
// array.add("hello");
// array.add(10);
Class c = array.getClass(); // 集合ArrayList的class文件对象
Method m = c.getMethod("add", Object.class);
m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello
m.invoke(array, "world");
m.invoke(array, "java");
System.out.println(array);
通用为某个对象的某个字段设置值工具类
public class Tool {
public void setProperty(Object obj, String propertyName, Object value)
throws NoSuchFieldException, SecurityException,
IllegalArgumentException, IllegalAccessException {
// 根据对象获取字节码文件对象
Class c = obj.getClass();
// 获取该对象的propertyName成员变量
Field field = c.getDeclaredField(propertyName);
// 取消访问检查
field.setAccessible(true);
// 给对象的成员变量赋值为指定的值
field.set(obj, value);
}
}
动态代理
本节移植Java回炉之反射(二)动态代理
查看完整源代码