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

时间:2016-05-23 08:43:04

标签: java generics reflection

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

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

来自Java doc:

  

实际结果类型是Class&lt; ? extends | X |&gt;其中| X |是个   擦除getClass所在表达式的静态类型   调用。例如,此代码片段中不需要强制转换:

     

数字n = 0;类&LT; ? extends Number&gt; c = n.getClass();

编辑:

  1. 找到this nice explanation 删除静态类型的含义。

  2. 有一种方法可以使用子类保留泛型类型信息,称为super type token。一个现在删除的答案有助于指出Guava库有一个convenient utility来利用它。

  3. 这里有great article反射性地提取泛型类型和一个很好的库,名为GenTyRef,简化了它

  4. 我分叉GenTyRef以添加对使用AnnotatedType(在Java 8中引入)的支持。它被称为GenAnTyRef(以及它在Maven Central中的位置)

2 个答案:

答案 0 :(得分:25)

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

因此,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) {

}

答案 1 :(得分:1)

首先,您需要将T定义为方法的类型参数:<T> void doSomething。然后你需要一个演员Class<? extends T>。所以这就是你如何组合起来的:

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