我正在使用一些注释来动态设置类中字段的值。由于我想要这样做,无论它是公共的,受保护的还是私有的,每次调用setAccessible(true)
方法之前,我都会在Field对象上调用set()
。我的问题是setAccessible()
调用对字段本身有什么影响?
更具体地说,它是一个私有字段,这组代码调用setAccessible(true)
。如果代码中的其他位置然后通过反射检索相同的字段,那么该字段是否已经可访问?或者getDeclaredFields()
和getDeclaredField()
方法每次都返回Field对象的新实例吗?
我想另一种陈述问题的方法是,如果我打电话给setAccessible(true)
,在我完成之后将它设置回原始值有多重要?
答案 0 :(得分:70)
使用setAccessible()
,您可以更改AccessibleObject
的行为,即Field
实例,但不会更改类的实际字段。这是documentation(摘录):
值
true
表示反射对象在使用时应禁止检查Java语言访问控制
一个可运行的例子:
public class FieldAccessible {
public static class MyClass {
private String theField;
}
public static void main(String[] args) throws Exception {
MyClass myClass = new MyClass();
Field field1 = myClass.getClass().getDeclaredField("theField");
field1.setAccessible(true);
System.out.println(field1.get(myClass)); // no exception
Field field2 = myClass.getClass().getDeclaredField("theField");
System.out.println(field2.get(myClass)); // IllegalAccessException
}
}
答案 1 :(得分:29)
getDeclaredField
方法每次都必须返回一个新对象,因为该对象具有可变accessible
标志。所以没有必要重置标志。您可以在this blog post中找到完整的详细信息。
答案 2 :(得分:1)
正如其他海报所示,setAccessible
仅适用于java.lang.reflect.Field
的该实例,因此不需要将辅助功能设置回原始状态。
...然而
如果您希望对field.setAccessible(true)
的呼叫保持持久,则需要使用java.lang.Class
和java.lang.reflect.Field
中的基础方法。面向公众的方法会向您发送Field
实例的副本,因此每次执行{{1}之后,"忘记" }}
class.getField(name)
答案 3 :(得分:0)
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class PrivateVariableAcc {
public static void main(String[] args) throws Exception {
PrivateVarTest myClass = new PrivateVarTest();
Field field1 = myClass.getClass().getDeclaredField("a");
field1.setAccessible(true);
System.out.println("This is access the private field-"
+ field1.get(myClass));
Method mm = myClass.getClass().getDeclaredMethod("getA");
mm.setAccessible(true);
System.out.println("This is calling the private method-"
+ mm.invoke(myClass, null));
}
}