一、什么是类的成员?
众所周知,Java反射可以在运行时获取类的成员。那么问题来了,什么是类的成员呢?一起来看一下Java 7给出的官方解释:
According to The Java Language Specification, Java SE 7 Edition, the members of a class are the inherited components of the class body including fields, methods, nested classes, interfaces, and enumerated types. Since constructors are not inherited, they are not members. This differs from the implementing classes of java.lang.reflect.Member.
以上信息可以理解为:
类的成员包括:从父类继承得到的成员变量,方法;内嵌的类,接口,枚举类型。因为构造方法无法被继承,所以不是类成员。
二、成员变量(field)
1. 获取成员变量
先来看一个对Class
API中获取成员变量方法的总结。
Class API | 通过List返回多个成员变量 | 返回父类成员变量 | 返回私有成员变量 |
---|---|---|---|
getDeclaredField() |
no | no | yes |
getField() |
no | yes | no |
getDeclaredFields() |
yes | no | yes |
getFields() |
yes | yes | no |
Class对象提供了四种方法来获取类的成员变量,其中getDeclaredField()
和getField()
都是需要通过提供变量名称来获取单一成员变量。getFields()
和getDeclaredFields()
则可以通过链返回多个成员变量。
Class c = ... // 获取Class对象
Field field = c.getField("fieldName") // 通过成员变量名称获取
Field[] fields = c.getFields() // 获取公有成员变量,包括父类的公有成员变量
通过以上表,我们可以得知无法通过这四种方法来获取父类的私有成员变量。
2. 获取成员变量的名字、类型和修饰器
(1). 名字
通过Field
类的Field.getName()
来获取变量名
Field field = ... // 获取成员变量对象
String fieldName = field.getName();
(2). 类型
通过Field
类的Field.getType()
来获取变量类型
Class c = String.class; // String 类
Field[] fields = c.getFields(); // 获取String类的成员变量
Object fieldType = fields[0].getType(); // 获取变量类型
(3). 修饰器
通过Field
类的Field.getModifiers()
来获取变量类型
Class c = String.class; // String 类
Field[] fields = c.getFields(); // 获取String类的成员变量
int modifier = fields[0].getModifiers(); // 所有修饰器都对应到了一个整型数值
Modifier.toString(modifier); // 将整型数值转成相应的修饰器字符串
Field
类还提供了Field.isSynthetic()
和Field.isEnumConstant()
方法。前者确定变量是否是合成的,后者确定变量是否属于枚举常量。
3. 获取成员变量值、对成员变量赋值
Class c = MyObject.class;
Field field = c.getField("fieldName");
MyObject newInstance = new MyObject(); // 创建对象实例
Object value = field.get(newInstance); // 从对象实例中获取成员变量的值
field.set(newInstance, value); // 对成员变量进行赋值
三、方法(method)
先看对Class
API中获取method
途径的总结。
Class API | 通过List返回多个方法 | 返回父类方法 | 返回私有方法 |
---|---|---|---|
getDeclaredMethod() |
no | no | yes |
getMethod() |
no | yes | no |
getDeclaredMethods() |
yes | no | yes |
getMethods() |
yes | yes | no |
获取方法(method)同样有四种途径,具体差别和获取成员变量一样,不再赘述。
需注意的是:使用
getMethod()
和getDeclaredMethod()
时需要给出参数的类型,不带参数时则要给出null
。比较神奇的是:当参数时原始值(primitive)类型时,你可以直接用int.class
,boolean.class
等作为参数类型。
Class c = String.class;
Method method1 = c.getMethod("charAt", int.class); // 通过方法名和参数类型int获取方法
Method method1 = c.getMethod("getBytes", new Class[]{String.class}); // 通过方法名和参数类型String获取方法
String methodName = method1.getName(); // 获取方法名
1. 获取类方法的参数类型和返回类型(Return Type)
Method method = ... // 获取方法
Class[] parameterTypes = method.getParameterTypes(); //获取参数类型
Class returnType = method.getReturnType(); // 获取返回类型
2. 获取类方法的修饰器
Method method = ...
int modifier = method.getModifiers();
3. 检查参数数量是否确定
Method method = ...
boolean varArgs = method.isVarArgs();
4. 调用方法(method)
通过Method
的invoke()
调用方法
Method method = String.class.getMethod("charAt", int.class);
Char returnValue = method.invoke("Hello", 4);
参考文献
Java Reflection - Tutorials
Java Reflection - Fields
Java Reflection - Methods