Java反射 - 访问受保护的字段

Mor*_*oro 33 java reflection field protected

如何通过反射从对象访问继承的受保护字段?

ken*_*418 54

您可能遇到的两个问题 - 该字段可能无法正常访问(私有),并且它不在您正在查看的类中,而是在层次结构的某个位置.

即使这些问题,这样的事情也会起作用:

public class SomeExample {

  public static void main(String[] args) throws Exception{
    Object myObj = new SomeDerivedClass(1234);
    Class myClass = myObj.getClass();
    Field myField = getField(myClass, "value");
    myField.setAccessible(true); //required if field is not normally accessible
    System.out.println("value: " + myField.get(myObj));
  }

  private static Field getField(Class clazz, String fieldName)
        throws NoSuchFieldException {
    try {
      return clazz.getDeclaredField(fieldName);
    } catch (NoSuchFieldException e) {
      Class superClass = clazz.getSuperclass();
      if (superClass == null) {
        throw e;
      } else {
        return getField(superClass, fieldName);
      }
    }
  }
}

class SomeBaseClass {
  private Integer value;

  SomeBaseClass(Integer value) {
    this.value = value;
  }
}

class SomeDerivedClass extends SomeBaseClass {
  SomeDerivedClass(Integer value) {
    super(value);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果有安全管理器,则会失败.您需要在PriviledgedAction中结束对setAccessible和getDeclaredField的调用,并通过java.security.AccessController.doPrivileged(...)运行它 (6认同)
  • 我全心全意的爱你 (2认同)

Mau*_*rry 6

field = myclass.getDeclaredField("myname");
field.setAccessible(true);
field.set(myinstance, newvalue);
Run Code Online (Sandbox Code Playgroud)


jwe*_*ich 6

使用反射来访问类实例的成员,使它们可访问并设置它们各自的值.当然,你必须知道你想要改变的每个成员的名字,但我想这不会是一个问题.

public class ReflectionUtil {
    public static Field getField(Class clazz, String fieldName) throws NoSuchFieldException {
        try {
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            Class superClass = clazz.getSuperclass();
            if (superClass == null) {
                throw e;
            } else {
                return getField(superClass, fieldName);
            }
        }
    }
    public static void makeAccessible(Field field) {
        if (!Modifier.isPublic(field.getModifiers()) ||
            !Modifier.isPublic(field.getDeclaringClass().getModifiers()))
        {
            field.setAccessible(true);
        }
    }
}

public class Application {
    public static void main(String[] args) throws Exception {
        KalaGameState obj = new KalaGameState();
        Field field = ReflectionUtil.getField(obj.getClass(), 'turn');
        ReflectionUtil.makeAccessible(field);
        field.setInt(obj, 666);
        System.out.println("turn is " + field.get(obj));
    }
}
Run Code Online (Sandbox Code Playgroud)


mrt*_*rts 6

使用FieldUtils.writeField(object, "fieldname", value, true)readField(object, "fieldname", true)Apache Commons lang3获取


Ste*_*ers 6

如果使用 Spring,ReflectionTestUtils提供了一些方便的工具,可以轻松地帮助解决此问题。

例如,要获取已知为 的受保护字段值int

int theIntValue = (int)ReflectionTestUtils.getField(theClass, "theProtectedIntField");
Run Code Online (Sandbox Code Playgroud)

或者设置该字段的值:

ReflectionTestUtils.setField(theClass, "theProtectedIntField", theIntValue);
Run Code Online (Sandbox Code Playgroud)