1 简介
反射是动态语言的关键,反射机制允许程序在执行期间改变对象内部结构,Java作为静态语言通过引入反射机制可以实现动态语言的这个特性,如:
- 获取类的内部信息
- 直接操作任意对象的内部属性和方法。
2 Java反射API
Class
类:反射的核心类,Field
类:java.lang.reflect
包下,表示类的成员变量,用于获取和设置类的属性。Method
类:表示类的方法,用于获取类中方法的信息或者执行方法。Constructor
类:表示类的构造方法。
3 Class对象
所有类型又有有Class对象:
- class、interface、enum
- []:数组
- annotation: 注解 @interface
- 基本数据类型
获取Class对象的方法:
- 调用运行时类的class属性:
Person.class
- 调用运行时对象的getClass()方法:
p.getClass()
- 调用
Class.forName()
静态方法:Class.forName("com.ywq.pojo.Person")
- 通过ClassLoader:
// 获取一个类加载器 ClassLoader classLoader = Reflection2.class.getClassLoader(); // 通过类加载器加载类 Class<?> clazz = classLoader.load("com.ywq.pojo.Person");
4 创建对象
通过反射创建对象有两种方式:
- 通过
Class
对象的newInstance()
方法,该方法调用类的默认的空构造器。Person p = (Person) clazz.newInstance();
- 通过
Constructor
对象的newInstance()
方法:// 通过反射获取构造器对象创建对象 Constructor<?> con = clazz.getDeclaredConstructor(String.class, int.class); Person p2 = (Person) con.newInstance("Tom", 18);
5 获取属性Field
- 获取所有public字段,包括父类:
Field[] fields = clazz.getFields();
- 获取当前类的所有字段,包括publlic, private…:
Field[] fields = clazz.getDeclaredFields();
通过修改字段信息:
public static void main(String[] args) {
// 通过反射修改字段信息
try {
Class<?> clazz = Class.forName("com.ywq.learn.reflect.Person");
Person p = (Person) clazz.newInstance();
Field name = clazz.getDeclaredField("name");
// 确保当前属性访问权限
name.setAccessible(true);
name.set(p, "哈哈");
// static 成员,set时obj参数可以为任意参数(包括null),
// 因为static成员是类所有,clazz包含其信息
Field num = clazz.getDeclaredField("static_num");
num.setAccessible(true);
num.set(null, 122);
System.out.println(num.get(p));
} catch (Exception e) {
e.printStackTrace();
}
}
6 获取方法Method
// 通过反射获取构造器对象创建对象
Constructor<?> con = clazz.getDeclaredConstructor(String.class, int.class);
Person p = (Person) con.newInstance("Tom", 18);
// 通过反射调用方法
Method setName = clazz.getDeclaredMethod("setName", String.class);
setName.invoke(p, "Mary");
Method show = clazz.getDeclaredMethod("show");
show.invoke(p);