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

kaq*_*qao 18 java generics reflection

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

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

来自Java doc:

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

数n = 0; 班级<?extends Number> c = n.getClass();

编辑:

  1. 找到了静态类型擦除意味着什么的很好的解释.

  2. 有一种方法可以使用子类保留泛型类型信息,称为超类型令牌.现在删除的答案有助于指出Guava库有一个方便的实用程序来利用它.

  3. 这是一篇关于反射性地提取泛型类型和一个很好的库的文章,名为GenTyRef,简化了它

  4. 我分叉了GenTyRef以增加对使用AnnotatedTypes的支持(在Java 8中引入).它被称为GenAnTyRef(它在Maven Central中)

Era*_*ran 25

静态类型的擦除items.get(0)Object(因为T在编译期间被擦除).

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

这将通过编译:

Class<? extends Object> clazz = items.get(0).getClass();
Run Code Online (Sandbox Code Playgroud)

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

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

}
Run Code Online (Sandbox Code Playgroud)

  • `类<?extends Object>`是多余的,`Class <?>`更简洁 (2认同)