我不得不问这个问题,我感到非常愚蠢,但是我没理解为什么以下的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();
编辑:
找到this nice explanation 删除静态类型的含义。
有一种方法可以使用子类保留泛型类型信息,称为super type token。一个现在删除的答案有助于指出Guava库有一个convenient utility来利用它。
这里有great article反射性地提取泛型类型和一个很好的库,名为GenTyRef,简化了它
我分叉GenTyRef以添加对使用AnnotatedType
(在Java 8中引入)的支持。它被称为GenAnTyRef(以及它在Maven Central中的位置)
答案 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();
...
}