【问题标题】:Access Nested Field using Java Reflection使用 Java 反射访问嵌套字段
【发布时间】:2020-01-06 15:27:31
【问题描述】:

假设我有几个这种风格的类:

public class A {
     public B element;
}

public class B {
     public C anotherElement; // where C refers to another type which contains types D, E, F, etc.....
}

我想遍历所有包含的子类(不继承)并获取嵌套对象树中所有字段的列表。但是,当我使用这样的反射代码时:

    Field[] myFields = providedObject.getClass().getDeclaredFields();
    for (Field myField : myFields) {
        // do something here?? to access the sub-fields of the class
        // if I print out myField.getName(), I get the element of class A, but I also want to access the anotherElement of class B (without hard-coding the name 'anotherElement', I want a full traversal of all nested fields)
    }

在“在此处执行操作”步骤中,我想访问 myField 的子字段,但我在 Field api 中看不到任何可以直接让我执行此操作的内容。我试过了:

myField.getDeclaringClass().getDeclaredFields() -> 这似乎返回了我们已经看到的相同元素,而不是子元素

myField.getClass().getDeclaredFields() -> 这似乎返回“Field”类的字段,而不是我的 A 或 B 类

那么我将如何从反射 api 访问嵌套字段?

谢谢。

【问题讨论】:

    标签: java reflection field


    【解决方案1】:

    这只是一点递归:

    public static void traverseDepthFirst(Object obj) { // May need throws/catch!
        if (obj == null) {
            // ... do something for null ...
            return;
        }
        // ... perhaps do something different for arrays, primitives, String, etc.
        for (Field field : obj.getClass().getDeclaredFields()) {
            field.setAccessible(true);
            // ... pre-traversal code ...
            traverseDepthFirst(field.get(obj));
            // ... post-traversal code ...
        }
    }
    

    编辑:这只会考虑叶类。包括超类。

    public static void traverseDepthFirst(Object obj) { // May need throws/catch!
        if (obj == null) {
            // ... do something for null ...
            return;
        }
        // ... perhaps do something different for arrays, primitives, String, etc.
        for (
            Class<?> clazz = obj.getClass();
            clazz != null;
            clazz = clazz.getSuperclass()
        ) {
            for (Field field : clazz.getDeclaredFields()) {
                field.setAccessible(true);
                // ... pre-traversal code ...
                traverseDepthFirst(field.get(obj));
                // ... post-traversal code ...
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      我添加了以下语句来退出递归方法。你可以随心所欲地改变它。

              if (clazz == null || clazz.isPrimitive() || !clazz.getPackage().getName().startsWith("com.vvv.stack02")) {
                  return;
              }
      

      主要思想是您需要通过键入以下行将字段转换为类。

      Class<?> fieldClass = myField.getType();
      
      
      public class Main {
      
          public static void main(String[] args) {
              printFields(A.class);
          }
      
          public static void printFields(Class<?> clazz) {
      
              if (clazz == null || clazz.isPrimitive() || !clazz.getPackage().getName().startsWith("com.vvv.stack02")) {
                  return;
              }
      
              Field[] myFields = clazz.getDeclaredFields();
              for (Field myField : myFields) {
                  System.out.println(clazz.getSimpleName() + "->" + myField.getType().getSimpleName() + ":" + myField.getName());
                  Class<?> fieldClass = myField.getType();
                  printField(fieldClass);
              }
      
          }
      
          public static class A {
              public B element;
          }
      
          public static class B {
              public C anotherElement; // where C refers to another type which contains types D, E, F, etc.....
          }
      
          public static class C {
              public Integer a;
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-18
        • 1970-01-01
        • 1970-01-01
        • 2012-03-18
        • 1970-01-01
        相关资源
        最近更新 更多