反射机制
反射是Java语言的一个特性,是Java被视为动态语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括modifiers(如public,static等)、superclass(如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。Java可以加载一个运行时才得知名称的class,获得其完整结构。
A Simple Example
1 | import java.lang.reflect.*; |
输出结果
1 | $ java DumpMethods java.util.Stack |
列出了java.util.Stack
类的所有方法名和签名。
这个程序用class.forName
加载特定的类,然后调用getDeclaredMethods
取出类中定义的方法列表。java.lang.reflect.Method
是一个代表类方法的类。
JDK中提供的Reflection API
Interfaces
AnnotatedElement
GenericArrayType
GenericDeclaration
InvocationHandler
Member
ParameterizedType
Type
TypeVariable
WildcardType
Classes
AccessibleObject
Array
Constructor
Field
Method
Modifier
Proxy
ReflectPermission
Exceptions
InvocationTargetException
MalformedParameterizedTypeException
UndeclaredThrowableException
Errors
GenericSignatureFormatError
Java反射机制提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任一个对象的方法
- 在运行时创建新类对象
在使用Java的反射功能时,基本首先都要获取类的Class对象,再通过Class对象获取其他的对象。
用于测试的类:
1 | class Type { |
1.获取类的Class对象
Class类的实例表示正在运行的Java应用程序中的类和接口。
- 调用getClass
1
2
3Boolean var1 = new Boolean("true");
Class classType1 = var1.getClass();
System.out.println(classType1); - 运用.class语法
1
2Class classType2 = Boolean.class;
System.out.println(ClassType2) - 运用static method Class.forName()
1
2Class classType3 = Class.forName("java.lang.Boolean");
System.out.println(classType3); - 运用primitive wrapper classes的TYPE语法(这里返回的是原生类型,和Boolean.class返回的不同)
1
2Class classType4 = Boolean.TYPE;
System.out.println(classType4);
2.获取类的Fields
可以通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值。Java的Class类提供了几个方法获取类的属性。
public Field getField(String name)
返回一个Field对象,它反映此Class对象所表示的类或接口的指定public成员字段。public Field[] getFields()
返回Field对象的数组,这些对象反映此Class对象所表示的类或接口的所有可访问public字段。public Field getDeclaredField(String name)
返回一个Field对象,它反映此Class对象所表示的类或接口的指定已声明字段。public Field[] getDeclaredFields()
返回Field对象的数组,这些对象反映出此Class对象所表示的类或接口声明的所有字段。
1 | Class classType = ExtendType.class; |
可见getFields和getDeclaredFields区别:
getFields返回的是声明为public的属性,包括父类中定义,
getDeclaredFields返回的是指定类定义的所有定义的属性,不包括父类的。
3.获取类的Method
通过反射机制得到某个类的某个方法,然后调用对应于这个类的某个实例的该方法。Class类提供了几个获取类方法的方法。
public Method getMethod(String name, Class<?>... parameterTypes)
返回一个Method对象,它反映此Class对象所表示的类或接口的指定public成员方法。public Method[] getMethods()
返回Method对象的数组,这些对象反映此Class对象所表示的类或接口的public成员方法,包括继承的方法。public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
返回一个Method对象,该对象反映此Class对象所表示的类或接口的指定已声明方法。public Method[] getDeclaredMethods()
返回Method对象的数组,这些对象反映此Class对象表示的类或接口声明的所有方法,但不包括继承的方法。
1 | Class classType = ExtendType.class; |
4.获取类的Constructor
通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例,Class类提供了几个方法获取类的构造器。
public Constructor<T> getConstructor(Class<?>... parameterType)
返回一个Constructor对象,它反映此Class对象所表示的类的指定public构造方法。public Constructor<?>[] getConstructors()
返回Constructor对象的数组,这些对象反映此Class对象所表示的类的所有public构造方法。public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回一个Constructor对象,它反映此Class对象所表示的类或接口的指定构造方法。public Constructor<?>[] getDeclaredConstructors()
返回Constructor对象的数组,这些对象反映此Class对象表示的类声明的所有构造方法。
1 | Constructor[] constructors = classType.getConstructors(); |
5.新建类的实例
通过反射机制创建新类的实例,有几种方法可以创建。
- 调用无自变量ctor
(1)调用类的Class对象的newInstance方法,该方法会调用对象的默认构造函数,如果没有默认构造函数,会调用失败。
1 | Class classType = ExtendType.class; |
(2)调用默认Constructor对象的newInstance方法
1 | Class classType = ExtendType.class; |
- 调用带参数ctor
(3)调用带参数Constructor对象的newInstance方法
1 | Class classType = ExtendType.class; |
6.调用类的函数
通过反射获取类Method对象,调用其Invoke方法调用此函数。
1 | Class classType = ExtendType.class; |
7.设置/获取类的属性值
通过反射获取类的Field对象,调用Field方法设置或获取值。
1 | Class classType = ExtendType.class; |