通常来说,使用反射 API 的第一步便是获取 Class 对象。在 Java 中常见的有这么三种。
- 使用静态方法 Class.forName 来获取。
- 调用对象的 getClass() 方法。
- 直接用类名 +“.class”访问。对于基本类型来说,它们的包装类型(wrapper classes)拥有一个名为“TYPE”的 final 静态字段,指向该基本类型对应的 Class 对象。
例如,Integer.TYPE 指向 int.class。对于数组类型来说,可以使用类名 +“[ ].class”来访问,如 int[ ].class。
除此之外,Class 类和 java.lang.reflect 包中还提供了许多返回 Class 对象的方法。例如, 对于数组类的 Class 对象,调用 Class.getComponentType() 方法可以获得数组元素的类型。
一旦得到了 Class 对象,我们便可以正式地使用反射功能了。下面我列举了较为常用的几项。
- 使用 newInstance() 来生成一个该类的实例。它要求该类中拥有一个无参数的构造器。
- 使用 isInstance(Object) 来判断一个对象是否该类的实例,语法上等同于 instanceof 关键字(JIT 优化时会有差别,我会在本专栏的第二部分详细介绍)。
- 使用 Array.newInstance(Class,int) 来构造该类型的数组。
- 使用 getFields()/getConstructors()/getMethods() 来访问该类的成员。除了这三个之外,Class 类还提供了许多其他方法,详见 [4]。需要注意的是,方法名中带 Declared 的不会返回父类的成员,但是会返回私有成员;而不带 Declared 的则相反。
getFields
getConstructors //获取一个对象
getMethods
当获得了类成员之后,我们可以进一步做如下操作。
使用 Constructor/Field/Method.setAccessible(true) 来绕开 Java 语言的访问限制。使用 Constructor.newInstance(Object[]) 来生成该类的实例。
使用 Field.get/set(Object) 来访问字段的值。
使用 Method.invoke(Object, Object[]) 来调用方法。
https://docs.oracle.com/javase/tutorial/reflect/