Вопрос по java – Отражение Java - влияние setAccessible (true)

84

Я использую некоторые аннотации для динамического задания значений полей в классах. Поскольку я хочу сделать это независимо от того, является ли он общедоступным, защищенным или частным, я являюсь звонкомsetAccessible(true) на объекте Field каждый раз перед вызовомset() метод. У меня вопрос, какое влияние оказываетsetAccessible() позвонить уже на само поле?

В частности, скажем, что это частное поле и этот набор вызовов кодаsetAccessible(true), Если бы в коде было какое-то другое место для извлечения того же поля с помощью отражения, будет ли это поле уже доступно? ИлиgetDeclaredFields() а такжеgetDeclaredField() методы возвращают новые экземпляры объекта Field каждый раз?

Я думаю, что другой способ сформулировать вопрос, если я позвонюsetAccessible(true)Насколько важно вернуть его к исходному значению после того, как я закончу?

Ваш Ответ

4   ответа
1

setAccessible применимо только к этому экземпляру вашегоjava.lang.reflect.Fieldпоэтому возвращение доступности в исходное состояние не требуется.

Тем не мение...

Если вы хотите, чтобы ваши звонкиfield.setAccessible(true) чтобы быть настойчивым, вы должны использовать базовые методы вjava.lang.Class а такжеjava.lang.reflect.Field, Методы публичного обращения отправляют васcopies изField экземпляр, так это"forgets" после каждого раза, когда вы делаете что-то вродеclass.getField(name)

import java.lang.reflect.*;
import sun.reflect.FieldAccessor;

public class Reflect {
    private static Method privateGetDeclaredFields;
    private static Method getFieldAccessor;

    public static Field[] fields(Class<?> clazz) throws Exception {
        return (Field[]) privateGetDeclaredFields.invoke(clazz, false);
    }

    public static <T> T get(Object instance, Field field) throws Exception {
        return ((FieldAccessor) getFieldAccessor.invoke(field, instance)).get(instance);
    }

    public static void set(Object instance, Field field, Object value) throws Exception {
        ((FieldAccessor) getFieldAccessor.invoke(field, instance)).set(instance, value);
    }

    static {
        try {
            // These are used to access the direct Field instances instead of the copies you normally get through #getDeclaredFields.
            privateGetDeclaredFields = Class.class.getDeclaredMethod("privateGetDeclaredFields", boolean.class);
            privateGetDeclaredFields.setAccessible(true);
            getFieldAccessor = Field.class.getDeclaredMethod("getFieldAccessor", Object.class);
            getFieldAccessor.setAccessible(true);
        } catch (Exception e) {
            // Should only occur if the internals change.
            e.printStackTrace();
        }
    }
}
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));
    }

}
29

getDeclaredField метод должен возвращать новый объект каждый раз, именно потому, что этот объект имеет изменяемыйaccessible флаг. Таким образом, нет необходимости сбрасывать флаг. Вы можете найти полную информацию вэтот блог.

66

setAccessible() вы меняете поведениеAccessibleObjectто естьField экземпляр, но не фактическое поле класса. Здесьдокументация (Выдержка):

A value of true indicates that the reflected object should suppress checks for Java language access control when it is used

И работающий пример:

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
    }

}
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededthrows ExceptionError: User Rate Limit ExceededNoSuchFieldExceptionError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы