Java反射 - setAccessible的影响(true)

时间:2012-05-17 15:33:38

标签: java reflection

我正在使用一些注释来动态设置类中字段的值。由于我想要这样做,无论它是公共的,受保护的还是私有的,每次调用setAccessible(true)方法之前,我都会在Field对象上调用set()。我的问题是setAccessible()调用对字段本身有什么影响?

更具体地说,它是一个私有字段,这组代码调用setAccessible(true)。如果代码中的其他位置然后通过反射检索相同的字段,那么该字段是否已经可访问?或者getDeclaredFields()getDeclaredField()方法每次都返回Field对象的新实例吗?

我想另一种陈述问题的方法是,如果我打电话给setAccessible(true),在我完成之后将它设置回原始值有多重要?

4 个答案:

答案 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.Classjava.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));
    }

}