Java反射–类字段
使用Java Reflection,我们可以获得有关类字段的信息,并在运行时获取和设置字段值。在Java Reflection API中,存在一个类java.lang.reflect.Field,该类具有用于访问字段类型,字段修饰符以及设置和获取字段值的方法。
获取字段实例
首先要获取Field类的实例,因为我们必须使用java.lang.Class的方法,因为该类是所有反射操作的入口。
有四种获取字段实例的方法
getField(String name)–返回一个Field对象,该对象表示类或者接口的公共成员字段。
getFields()–返回一个包含Field对象的数组,该对象反映了该类或者接口的所有可访问公共字段。
getDeclaredField(String name)–返回一个Field对象,该对象反映此Class对象表示的类或者接口的指定声明字段(甚至私有)。
getDeclaredFields()–返回一个Field对象数组,该数组反映由该Class对象表示的类或者接口声明的所有字段。这包括公共,受保护,默认(程序包)访问和私有字段,但不包括继承的字段。
获取有关类字段的信息– Java示例
本示例说明如何获取信息,例如类型,类的单个/所有字段的修饰符。使用的Field类的方法是
Field类的getType()方法返回该字段的声明类型。
字段类的getModifiers()方法以整数形式返回字段的修饰符。
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Set;
public class FieldReflectionDemo {
public String str = "Reflection";
private int i;
public boolean flag = false;
public Set<String> citySet;
public static void main(String[] args) {
try {
FieldReflectionDemo obj = new FieldReflectionDemo();
Class<?> c = obj.getClass();
// get specific field
Field f = c.getField("str");
// getting field type
Class<?> type = f.getType();
// getting field modifiers
int mod = f.getModifiers();
System.out.println("Field name - " + f.getName());
System.out.println("Field type - " + type.getName());
System.out.println("Field modifiers - " + Modifier.toString(mod));
System.out.println("--- Getting all fields ---");
Field[] fields = c.getDeclaredFields();
for(Field field : fields) {
System.out.println("Field name - " + field.getName());
System.out.println("Field type - " + field.getType());
System.out.println("Field modifiers - " + Modifier.toString(field.getModifiers()));
}
} catch (NoSuchFieldException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出:
Field name - str Field type - java.lang.String Field modifiers - public --- Getting all fields -- Field name - str Field type - class java.lang.String Field modifiers - public Field name - i Field type - int Field modifiers - private Field name - flag Field type - boolean Field modifiers - public Field name - citySet Field type - interface java.util.Set Field modifiers - public
获取和设置值
为了获取值,有一个get(Object obj)方法,该方法返回指定对象上此Field表示的字段的值。
对于设置值,有一个set(Object obj,Object value)方法,该方法将指定对象参数上此Field对象表示的字段设置为指定的新值。
import java.lang.reflect.Field;
import java.util.Set;
public class FieldReflectionDemo {
public String str = "Reflection";
private int i;
public boolean flag = false;
public Set<String> citySet;
public static void main(String[] args) {
try {
FieldReflectionDemo obj = new FieldReflectionDemo();
Class<?> c = obj.getClass();
// get specific field
Field f = c.getField("str");
// show value - get method
System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));
// set new value
f.set(obj, "New Value");
System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));
} catch (IllegalAccessException | NoSuchFieldException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出:
Field name- str Value- Reflection Field name- str Value- New Value
获取和设置私有字段的值
我们甚至可以使用Reflection设置私有字段的值。为此,我们需要使用setAccesssible()方法将accessibility设置为true。
在示例中,我们有一个带有一个私有int字段i的Access类。在FieldReflectionDemo类中,我们将使用反射来访问该字段并为其设置值。如果我们未使用setAccesssible()方法设置访问标记,则会引发IllegalAccessException,如下所示。
class Access{
private int i;
}
public class FieldReflectionDemo {
public String str = "Reflection";
public boolean flag = false;
public Set<String> citySet;
public static void main(String[] args) {
try {
Access obj = new Access();
Class<?> c = obj.getClass();
// get specific field
Field f = c.getDeclaredField("i");
// show value - get method
System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));
// set new value
f.set(obj, 7);
System.out.println("Field name- " + f.getName() + " Value- " + f.get(obj));
} catch (IllegalAccessException | NoSuchFieldException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出:
java.lang.IllegalAccessException: class com.theitroad.programs.FieldReflectionDemo cannot access a member of class com.theitroad.programs.Access with modifiers "private"
进行此更改后,再次运行,我们甚至可以访问私有字段。
Field f = c.getDeclaredField("i");
f.setAccessible(true);
输出:
Field name- i Value- 0 Field name- i Value- 7

