【问题标题】:Iterate through generic class遍历泛型类
【发布时间】:2025-12-25 15:00:12
【问题描述】:

是否有可能打印出类中每个字段的名称和类型?现在我有以下代码

try {
   for (Field field : obj.getClass().getDeclaredFields()) {
   System.out.println("User Preferences " + field.getName()
                     + " - " + field.getType());
   }
}catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
}

其中显示:

User Preferences customer - class java.lang.String
User Preferences token - class java.lang.String
User Preferences class1 - class com.activity.webservice.Login$Class1

这就是我想要得到的(几乎)。

问题是让它进入自定义类 Class1。 Class1 类中可以有多个类,也可以没有类。 Class1 类可以有多个字段,也可以没有字段。

我想要这样的东西打印出来

User Preferences customer - class java.lang.String
User Preferences token - class java.lang.String
User Preferences class1 - class com.activity.webservice.Login$Class1
User Preferences string1 - class java.lang.String
User Preferences class2 - class com.activity.webservice.Login$Class2
User Preferences string2 - class java.lang.String
User Preferences string3 - class java.lang.String

如何遍历未知数量的字段和类?

感谢您的帮助

编辑

这是我的登录类的结构

public class Login {

     public String token;   
     public String customerid;
     public Class1 class1;

     public class Class1 {
            public Class2 class2;
            public String string1;

            public class Class2 {
                    public int int1;
                    public String string2;
                    public String string3;
            }
     }
}

【问题讨论】:

  • 什么数据结构保存这些信息?
  • @m0skit0 这将是它自己的类中的一个方法。无论我传入什么对象,我都可以获得我需要的信息
  • 使用递归方法——每一级进入成员类
  • @Bhaskar 我将如何传入新类进行迭代?我会让 obj = Class1 然后再次调用我的方法吗?当我没有看到另一个类时停止该方法?
  • 您可以将成员字段的 Class 传递到递归调用中,如果当前 Class 令牌内部没有字段,即它是原始字段,则停止。 (或者想出你自己的自定义逻辑,何时停止进一步向下搜索)

标签: java android reflection iteration


【解决方案1】:

以下是有关如何递归执行此操作的总体思路。只需传入您想要字段的类,它也应该递归检查所有子类的字段。

// Call this method to get the list of fields.
public static List<String> getAllFields(Class<?> clazz) {
    List<String> results = new ArrayList<String>();
    getFieldDescsForClass(clazz, results);
    return results;
}

private static void getFieldDescsForClass(Class<?> clazz, List<String> outList) {
    // Loop over all the fields and add the info for each field
    for (Field field : clazz.getDeclaredFields()) {
        // Ignore synthetic fields
        if (!field.isSynthetic()) {
            outList.add(String.format("User Preferences %s - %s", field.getName(), field.getType()));
        }
    }

    // For any internal classes, recursively call this method and add the results
    // (which will in turn do this for all of that subclass's subclasses)
    for (Class subclazz : clazz.getDeclaredClasses()) {
        getFieldDescsForClass(subclazz, outList);
    }
}

【讨论】:

  • 我不确定你的意思。
  • 糟糕,我误解了这个问题。对不起!
  • @kcoppock 检查我上面所做的编辑。此方法进入 Class1 但返回一个随机长变量。这种方法适用于我的结构吗?
  • 随机长?你的类是可序列化的吗?它可能会返回序列号。这当然应该适用于您的班级结构;你没有看到它递归工作吗?
  • 那些是对外部类的隐式引用(因为内部类是非静态的)。您可以通过在添加到列表之前检查field.isSynthetic() 来避免捕获这些。如果isSynthetic() 为真,则为隐式添加字段。
【解决方案2】:
public class Test {
static List structure = new ArrayList();

static void getClassStructure(Class clazz, List structure){
    Field[] fields = clazz.getDeclaredFields();
    for(Field f : fields){
        structure.add(f.getType());
    }

    Class[] classes = clazz.getDeclaredClasses();
    for(Class c : classes){
        getClassStructure(c, structure);
    }
}

public static void main(String[] args) {
    Class clazz = new Login().getClass();
    getClassStructure(clazz, structure);
    System.out.println(structure);

}

}

测试过

class Login {

public String token;   
public String customerid;
public Class1 class1;

public class Class1 {
       public Class2 class2;
       public String string1;

       public class Class2 {
               public int int1;
               public String string2;
               public String string3;
       }
}

}

输出:

类 java.lang.String

类 java.lang.String

类登录$Class1

类登录$Class1$Class2

类 java.lang.String

类登录

int

类 java.lang.String

类 java.lang.String

类登录$Class1

【讨论】: