使用Java反射获取嵌套字段(对象类型字段的字段)的值

时间:2019-06-03 13:34:01

标签: java reflection

有一类,其某些字段是用户定义的对象。我要去:

  1. 获取Primary class的字段并遍历它们以获取其值。

    1.1遇到具有对象类型的字段时,请遍历具有自己字段的对象

  2. 获取这些嵌套字段(对象类型字段的字段)的值

问题出在步骤2;当我获得对象字段的字段时,无法获取它们的值,因为我需要将一个对象传递给field.get(object)来指示要从中提取字段值的对象,但是如何访问对象类型是我们谈话领域中的当前对象?

代码如下:

public class PrimaryClass {
    String str;
    int num;
    MyClass cls;
}


PrimaryClass primaryObject = new PrimaryClass();

Field[] primaryObjectFields = primaryObject.getClass().getDeclaredFields();

// ... One of the fields is :  MyClass foo.bar.cls
// Assuming stored with name of clsField 

Field[] myClassObjectFields = clsField.getType().getDeclaredFields();

for (Field f : myClassObjectFields) {

    String fieldValue = f.get(primaryObject /* What to pass here? */); 
    // !!!! The above line Doesn't work since the primary Object doesn't have access to its child's fields

    System.out.println(fieldValue);

}

当我获得第一级字段(并将其设置为setAccessible(true)可以访问)时,要获取其内部对象字段,请调用以下命令:

topLevelField.getClass().getDeclaredField("details"); 
topLevelField.setAccessible(true);
topLevelField.get(primaryObject);

但是无法访问在父对象内部实例化的对象字段并得到以下错误:

java.lang.IllegalArgumentException: Can not set java.util.List field com.foo.Bar.details to com.foo.Bar

内部对象是List对象,但在某些情况下也可以是非列表对象。

2 个答案:

答案 0 :(得分:1)

Here is a cool tutorial 可以帮助您入门。 通常,get返回一个对象,然后可以将其强制转换为所需的任何类型。另外,您可以询问字段的类型,并根据字段的类型执行一些逻辑。 还有一些很酷的方法可以使您更好地熟悉clazz.isAssignableFrom(obj.getClass())

您可以详细了解here

答案 1 :(得分:0)

要调用field.get(instance),您需要一个声明该字段的类型的实例instance。因此,对于要为其检索字段列表的每个嵌套级别,还需要检索相应的字段值列表。这很容易解释,没有循环,但是一旦在每个嵌套级别的第一个字段中使用了它,就应该很容易从下面的示例重新创建迭代,为简单起见,该示例假定采用以下自适应结构:

class PrimaryClass {
    MyClass cls = new MyClass();
    String str = "foo";
}

class MyClass {
    String value= "test";
}

在顶层,我们有您的主要实例:

PrimaryClass primaryObject = new PrimaryClass();
Field[] primaryObjectFields = primaryObject.getClass().getDeclaredFields();

要处理第一个字段,我们同时检索字段的类型及其值:

Class<?> primaryObjectField1Type = primaryObjectFields[0].getType();
Object primaryObjectField1Value = primaryObjectFields[0].get(primaryObject);

请注意如何获取字段的值,我们需要传入对声明字段primaryObject的类的实例(primaryObjectFields)的引用。我们只是为每个嵌套级别执行此操作:

Field[] myClassObjectFields = primaryObjectField1Type.getDeclaredFields();

Class<?> myClassObjectField1Type = myClassObjectFields[0].getType();
Object myClassObjectField1Value = myClassObjectFields[0].get(primaryObjectField1Value);

请注意,现在传递给我们的实例是primaryObjectField1Value,它是声明字段MyClass的{​​{1}}的实例。

因此,通常,解决您的问题的方法是检索字段值及其类型,并将这些值传递给value