【问题标题】:Get non-static inherited field with reflection使用反射获取非静态继承字段
【发布时间】:2017-10-07 04:13:01
【问题描述】:

如何获得扩展类的非静态字段

我知道如何获取静态字段,但不知道如何从实例中获取字段


我已经试过了

Field commandName = command.getField("name");

但我得到了NoSuchFieldException 异常


这些是类:

public class A extends B{

    public A(String name){
        super(name);
    }
}

public class B{
    private String name;
    protected B(String name){
        this.name = name;
    }
}

我需要从外部类中获取名称。

【问题讨论】:

  • Java 中的Field 类不存储对象的值。但是,您可以使用 get(Object obj) 方法从对象(如果对象包含此类字段)中获取值。
  • 请注意,getFields() 会显示您可以通过getField(...) 访问的所有字段。如文档中所述,这只是公共成员
  • @Zabuza A NoSuchFieldException 可能很明显,因为找不到字段,但为什么找不到它可能是个问题。当某个字段不可公开访问时,可以抛出 NoSuchFieldException,即使将正确的名称传递给 getField(String)
  • @Kröw 完全正确。也就是说,我认为,OP没有考虑。
  • 啊,编辑说清楚了,该字段确实是私有。那么它是一个副本:Access to private inherited fields via reflection in Java.

标签: java reflection


【解决方案1】:

有一个类,Test,例如:

public class Test {

    public int field1;

}

还有一个子类SubTest,例如:

//This class extends Test
public class SubTest extends Test  {

    public SubTest(int value) {
        field1 = value;//field1 is public, so we can access it from subclass.
    }

}

我们可以使用Field 对象执行以下操作:

public static void main(String[] args)
            throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        SubTest t0 = new SubTest(-10), t1 = new SubTest(0), t2 = new SubTest(10);

        Field f = SubTest.class.getField("field1");
        System.out.println(f.get(t0));
        System.out.println(f.get(t1));
        System.out.println(f.get(t2));

    }

打印:

-10
0
10

说明:Java 中的Field 类可以从Class 对象(不是类的实例)中获得,并可用于操作/读取它所代表的实际字段在物体上。在此示例中,我们获得了代表 field1Field 类,然后我们使用它从我们创建的每个 SubTest 中获取实际字段的值。

请注意 main 方法抛出的异常。 Java 反射有时会抛出许多已检查的异常。

如果您的超类 (Test) 中的字段是 private,您将需要获取您的类的超类(即SubTest 的超类),然后获取 声明的领域。请参阅 Zabuza 指出的this link 以了解更多信息。

【讨论】:

  • 我使用Field commandName = commandInstance.getClass().getField("name"); commandName.setAccessible(true); String name = (String) commandName.get(commandInstance); 问题是我得到NoSuchFieldException 异常
  • 这意味着问题是由您的第一条语句引发的。特别是说:getField("name"); 确保name 字段是公共的,并且可以从任何调用getField 的地方访问。
【解决方案2】:

通过使用 反射 API

可以从myObject.getClass() 访问这些方法,例如myObject.getClass().getDeclaredFields()

这是Classdocumentation

请注意,Class#getField 方法也会在您的对象 (documentation) 的超类 中进行搜索。但正如文档中明确指出的那样,此方法仅搜索 public members


在您的具体示例中,您尝试访问 super classprivate 成员。为此,您首先需要获取对该超类的引用并将该字段设为 public,否则您将无法访问它。之后,您可以使用上述方法访问该字段:

A a = new A("foo");

// Make name public
Field nameField = a.getClass().getSuperClass().getDeclaredField("name");
nameField.setAccessible(true);

// Access the name
String name = (String) nameField.get(a);

【讨论】:

  • 在问题中它指出“扩展类”。这是否意味着他想要一个继承的领域?如果是这样:getField 可能会更好。
  • 我得到一个 NoSuchFieldException。我认为问题在于该字段不是静态的,所以我应该从实例中获取它
  • myObjectcar(在上面的示例中)是类的实例,而不是类名。它应该完美地工作。正如已经在您的问题中评论过的那样,您可能做错了什么。例如。试图访问不可访问的字段或类似的东西。
  • @Galgo 在 Java 中,Field 对象不代表对象字段的值。它们代表对象定义中的数据持有者:一个类。当您获得 Field 本身时,您无法从实例中获取它。它必须从一个类中获得。当您获取实例中实际字段的值时,您可以使用从实例的类中获得的Field
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
相关资源
最近更新 更多