Java反射——字段
使用java反射,你可以在运行时检查类的字段(成员变量)并且get/set它们的值。这些是通过Java类java.lang.reflect.Field做的。
本文将会给出更详细的关于Field对象的信息。请记住也去查阅Sun的JavaDoc。
下面是主题列表:
Obtaining Field Objects (获取Field对象) Field Name (字段名) Field Type (字段类型) Getting and Setting Field Values (get/set字段的值)
获取 Field 对象
从Class对象中获取Field对象。这里有一个例子:
Class aClass = ...//obtain class object
Field[] fields = aClass.getFields();
数组 fields 将会存储在类中声明的所有为public的字段的Field对象。
如果你知道你想要访问的字段的字段名,你可以像这样来访问它:
Class aClass = MyObject.class
Field field = aClass.getField("someField");
上面的例子将会返回Field实例,和下面MyObject声明的字段someField对应:
public class MyObject{
public String someField = null;
}
如果不存在和方法 getField()
接受的参数一致的字段,会抛出NoSuchFieldException异常。
字段名
一旦你获取了一个Field实例,你可以像这样通过Field.getName()方法取得字段名:
Field field = ... //obtain field object
String fieldName = field.getName();
字段类型
你可以通过Field.getType() 方法取得字段类型(String, int etc.) :
Field field = aClass.getField("someField");
Object fieldType = field.getType();
字段值的获取和设置
一旦你获取了Field对象的引用,你可以像这样通过Field.get()方法和Field.set()方法get/set字段的值:
Class aClass = MyObject.class
Field field = aClass.getField("someField");
MyObject objectInstance = new MyObject();
Object value = field.get(objectInstance);
field.set(objectInstance, value);
传给get和set方法的参数objectInstance必须是拥有该字段的实例。
在上面的例子中,用了一个MyObject的实例,因为someField是类MyObject的成员实例。
如果字段是静态字段(public static …),则传null作为get和set方法的参数,而不是上面传的objectInstance。
私有字段
尽管普遍的观点是不能直接访问私有字段和私有方法的,实际上通过Java反射是可以访问其他类的私有字段和私有方法的。它甚至不是那么困难。在单元测试期间很容易使用。本文将介绍你怎么做。 注:这个只会作用在运行独立的Java应用程序时,如写单元测试和常规应用。
如果你尝试在Java Applet内使用它,你需要处理好SecurityManager。
但是,因为这不是你经常要做的事情,所以在本文中将不会涉及它。
为了访问私有字段,你需要调用Class.getDeclaredField(String name)方法或者Class.getDeclaredFields()方法。
Class.getField(String name)和Class.getFields()方法只会返回public的字段,所有它们不会工作。
代码
下面是一个简单的例子,通过Java反射去访问一个类的私有字段:
public class PrivateObject {
private String privateString = null;
public PrivateObject(String privateString) {
this.privateString = privateString;
}
}
PrivateObject privateObject = new PrivateObject("The Private Value");
Field privateStringField = PrivateObject.class.getDeclaredField("privateString");
privateStringField.setAccessible(true);
String fieldValue = (String) privateStringField.get(privateObject);
System.out.println("fieldValue = " + fieldValue);
这段代码示例将会打印出文本“fieldValue = The Private Value”,是PrivateObject实例在代码示例最开始赋值给私有字段privateString的。
注意这里使用的方法PrivateObject.class.getDeclaredField(“privateString”)。
是这个方法调用返回了私有字段的值。这个方法只会返回在给定类里声明的字段的值,而不是其他任何在超类里声明的字段的值。
仅仅针对反射,通过调用 Field.setAccessible(true)
方法,关闭了对特定的Field实例的访问检查。
现在你可以访问它,尽管它是private,或者protected,或者是package scope,即使调用者不在这个范围内。
你仍然不能通过一般的代码去访问这些字段。编译器不允许这样干。
参考资料
http://tutorials.jenkov.com/java-reflection/index.html