测试局部朗读

18.4 使用反射生成并操作对象 18.4.3 访问成员变量值

通过Class对象的getFields()getField()方法可以获取该类所包括的全部成员变量或指定成员变量(Field对象).

Field类

Field提供了如下两组方法来读取或设置指定成员变量的值。

访问基本类型的成员变量

  • getXxx(Object object):获取object对象的该成员变量的值。此处的Xxx对应8种基本类型,
  • setXxx(Object object,Xxx value):将object对象的该成员变量设置成value值。此处的Xxx对应8种基本类型,

访问引用类型的成员变量

对应引用类型,直接使用getset方法即可

  • get(Object object):获取object对象的该成员变量的值。
  • set(Object object,Xxx value):将object对象的该成员变量设置成value值。

使用这两个方法可以随意地访问指定对象的所有成员变量,包括private修饰的成员变量。

程序示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import java.lang.reflect.*;
class Person
{
//私有的成员变量
private String name;
//私有的成员变量
private int age;
public String toString()
{
return "Person[name:" + name +
" , age:" + age + " ]";
}
}
public class FieldTest
{
public static void main(String[] args)
throws Exception
{
// 创建一个Person对象
Person p = new Person();
// 获取Person类对应的Class对象
Class<Person> personClazz = Person.class;
// 获取Person的名为name的成员变量
// 使用getDeclaredField()方法表明可获取各种访问控制符的成员变量
Field nameField = personClazz.getDeclaredField("name");
// 设置通过反射访问 name 成员变量时 取消访问权限检查
nameField.setAccessible(true);
// 调用set()方法为p对象的name成员变量设置值
nameField.set(p , "小明");

// 获取Person类名为age的成员变量
Field ageField = personClazz.getDeclaredField("age");
// 通过反射访问 age 成员变量时 取消访问权限检查
// (要在getter和setter方法之前设置)
ageField.setAccessible(true);
// 调用setInt()方法为p对象的age成员变量设置值
ageField.setInt(p , 30);
// 获取p对象的age成员变量的值
System.out.println("p对象的age成员变量的值:"+ageField.getInt(p));
System.out.println(p);
}
}

运行结果:

1
2
p对象的age成员变量的值:30
Person[name:小明 , age:30 ]

代码详解

上面程序中先定义了一个Person类,该类里包含两个private成员变量:nameage,在通常情况下,这两个成员变量只能在Person类里访问。但本程序FieldTestmain()方法中通过反射修改了Person对象的nameage两个成员变量的值。

  • 代码:personClazz.getDeclaredField("name");中的getDeclaredField方法获取了名为name的成员变量,注意此处不是使用getField方法,因为**getField方法只能获取public访问控制的成员变量,而getDeclaredField方法则可以获取所有的成员变量**:
  • 代码:nameField.setAccessible(true);设置通过反射访问成员变量name时不受访问权限的控制;
  • 代码nameField.set(p , "Yeeku.H.Lee");修改了Person对象的name成员变量的值。

修改Person对象的age成员变量的值的方式与此完全相同。
编译、运行上面程序,会看到如下输出:

1
Person[name:Yeeku.H.Lee , age:30 ]

总结

Class对象的**getField方法只能获取public访问控制的成员变量,而getDeclaredField方法则可以获取所有的成员变量**在获取(get)或者设置(set)某个私有的成员变量之前,必须先调用该成员变量(Field)setAccessible方法,并把参数设置为true.
例如要获取成员变量name的值之前,要先调用:nameField.setAccessible(true);`