【问题标题】:Get List of Classes from an object in java从java中的对象获取类列表
【发布时间】:2018-11-01 08:23:30
【问题描述】:

我目前正在尝试创建一个独特的List<Class> classList,例如其中包含一个对象的所有类

DemoObject.java

public class DemoObject {

    private Integer id;
    private String name;
    private BigDecimal price;
    private Boolean isActive;
    private List<NestedDemoObject> nested;
}

NestedDemoObject.java

public class NestedDemoObject {

    private Integer id;
    private String nameNest;
    private Boolean isActive;
}

我要创建的是一个方法public List&lt;Class&gt; getDistinctClasses(Class cl);,您将其作为输入,例如DemoObject.class,并返回一个列表

[DemoObject.class, Integer.class, String.class, BigDecimal.class, Boolean.class, List.class, NestedDemoObject.class]

NestedDemoObject.class 的另一个例子是

[NestedDemoObject.class, Integer.class, String.class, Boolean.class]

我尝试使用来自Class.getDeclaredClasses() 没有任何运气。 有什么方法可以使用 Reflection API 从对象中获取所有嵌套类?

感谢任何帮助或指导。

【问题讨论】:

  • 我相信您正在寻找的是Fields 的类,对吗?
  • 是的,我希望获取所有不同的字段类,包括根对象类(将我的示例帖子更改为包含和根对象类)
  • @ohlec 用 getDeclaredFields() 尝试了 Mark 的解决方案,效果很好,但正如你所说,以这种方式获取 NestedDemoObject 是不可能的。有什么可能的解决方法吗?
  • @ohlec 其实你是不对的。字段知道它们自己的通用类型。请在单独的帖子中查看我的答案。
  • @ETO 确实,谢谢。为了简洁,我将删除我的 cmets。

标签: java class reflection


【解决方案1】:

Mark 提供的解决方案部分正确。您正在尝试从声明的字段中检索类的正确方法。但是getType() 方法并没有显示泛型类型。

为了访问泛型类型,您应该改用Field.getGenericType()。它将类作为Type 对象返回。 Field 对象知道它们自己的类型(它们不会被删除,因为人们可能会误认为它们)。 这是一个使用泛型打印类型的 java 1.8+ 示例:

Arrays.stream(DemoObject.class.getDeclaredFields())
            .map(Field::getGenericType)
            .map(Type::getTypeName)
            .distinct()
            .forEach(System.out::println);

它将打印以下结果:

java.lang.Integer
java.lang.String
java.math.BigDecimal
java.lang.Boolean
java.util.List<com.eto.sandbox.NestedDemoObject>

如果您想使用泛型类型或出于任何原因解析它们,那么您可以使用以下示例:

 Arrays.stream(DemoObject.class.getDeclaredFields())
            .map(Field::getGenericType)
            .distinct()
            .forEach(type -> {
                if (type instanceof Class) {
                    // This is a simple class
                } else if (type instanceof ParameterizedType) {
                    // This is a generic type. You can parse its parameters recursively.
                }
            });

【讨论】:

  • 感谢您的回答,我将对其进行测试。我认为这样的事情可以工作
  • @PanosK,不客气!如有任何问题,请随时提出。
  • 顺便说一句,看看ParameterizedType.getActualTypeArguments() 方法。它提取通用子类型。
  • 请注意,关于泛型类型的这些信息在运行时可能不存在 - 但这几乎是边缘情况,就像一些混淆代码一样。由于 JVM 不需要此信息,因此可以将其剥离,但默认情况下会包含此信息。所以在大多数情况下,这样的解决方案是完美的。
【解决方案2】:

也许这会为您指明正确的方向:

for (Field f : DemoObject.class.getDeclaredFields()) {
    System.out.println(f.getType().getName());
}

打印出来:

java.lang.Integer
java.lang.String
java.math.BigDecimal
java.lang.Boolean
java.util.List

您可以通过Class.forName 之类的方式获取类实例。

我觉得 getDeclaredClasses 也不适合我,这很奇怪,我会调查一下。当我知道更多时,我会更新答案。

更新

getDeclaredClasses 打印在类中定义的类,如下所示:

class DemoObject {

    private Integer id;
    private String name;
    private BigDecimal price;
    private Boolean isActive;
    private List<NestedDemoObject> nested;

    public class InnerClass {

    }
}

然后执行getDeclaredClasses:

for (Class<?> f : DemoObject.class.getDeclaredClasses()) {
    System.out.println(f.getName());
}

打印值:

DemoObject$InnerClass

【讨论】:

  • @PanosK 我已经更新了我的答案,弄清楚了getDeclaredClasses 的实际工作原理。
  • 好的,非常感谢您的帮助,所以我必须使用 getDeclaredFields() 并以某种方式获取在 List 上声明的 NestedDemoObject 的类型
猜你喜欢
  • 1970-01-01
  • 2014-09-28
  • 2020-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-29
相关资源
最近更新 更多