如何从List<T>获得Class<T>

2022-09-02 21:11:15

我觉得不得不问这个问题非常愚蠢,但我不明白为什么下面的Java代码不能编译:

void <T> doSomething(List<T> items) {
    Class<? extends T> clazz = items.get(0).getClass();
    ...
}

来自 Java 文档:

实际结果类型为 Class< ?扩展|X|>|十|是调用 getClass 的表达式的静态类型的擦除。例如,此代码片段中不需要强制转换:

数字 n = 0;类< ?extends Number> c = n.getClass();

编辑:

  1. 找到了这个很好的解释,说明静态类型的擦除意味着什么。

  2. 有一种方法可以使用子类(称为超类型标记)保留泛型类型信息。现在删除的答案很有帮助地指出,番石榴库有一个方便的实用程序来利用这一点。

  3. 这是一篇关于反射性地提取泛型类型的好文章,以及一个名为GenTyRef的不错的lib,简化了它

  4. 我分叉了GenTyRef来添加对使用s的支持(在Java 8中引入)。它被称为GeantyRef(它位于Maven Central)AnnotatedType


答案 1

静态类型的擦除是(因为在编译过程中被擦除)。items.get(0)ObjectT

因此,返回 a,而不是 a,这解释了尝试分配失败的原因。items.get(0).getClass()Class<? extends Object>Class<? extends T>

这将通过编译:

Class<? extends Object> clazz = items.get(0).getClass();

如果希望该方法知道泛型参数的 ,则可以将其作为附加参数传递。Class

void doSomething(List<T> items, Class<T> clazz) {

}

答案 2

首先,您需要将 T 定义为方法的类型参数:.然后,您需要强制转换为 。所以这就是你如何组合在一起:<T> void doSomethingClass<? extends T>

<T> void doSomething(List<T> items) {
    Class<? extends T> clazz = (Class<? extends T>) items.get(0).getClass();
    ...
}