我使用.class
- 运算符向泛型类提供有关包含类型的信息。对于非通用包含类型,例如Integer.class
,这没有任何问题。但是所包含的类型是通用的,例如List<Integer>.class
或List.class
导致类转换的编译时错误。
有一种方法可以规避错误,但我很好奇这里发生了什么。有人可以解释发生了什么吗?为什么事情就像它们一样?以及解决问题的最佳方法是什么?
以下行说明了问题:
请注意,外部泛型类型需要Class<T>
作为参数,因此在这种情况下Class<List<Integer>>
。
Class<Integer> tInt = Integer.class; // Works as expected.
Class<List> tList = List.class; // Works with warning, but is not
// what i'm looking for.
Class<List<Integer>> tListInt1 = List.class; // Error
Class<List<Integer>> tListInt2 = (Class<List<Integer>>) List.class; // Error
Class<List<?>> tListGeneric = (Class<List<Integer>>) List.class; // Error
下一行有效:
Class<List<Integer>> tListInt3 =
(Class<List<Integer>>) ((Class<Integer>)List.class);
为什么tListInt2
和tListGeneric
的声明会给出错误?
为什么使用tListInt3
进行向上转换然后向下转换不会产生错误?
是否有更好的方式来声明tListInt3
?
亲切的问候,
Kasper van den Berg
PS。如果您希望将代码视为需要此类型信息的外部通用容器,请告诉我们。如果需要,我会发布它。
答案 0 :(得分:27)
Class<List<Integer>> tListInt3 =
(Class<List<Integer>>) ((Class<Integer>)List.class);
不起作用。你可能意味着
Class<List<Integer>> tListInt3 =
(Class<List<Integer>>) ((Class)List.class);
我们总是可以通过向上转换然后向下转换
从一种类型转换为另一种类型 Integer x = (Integer)(Object)"string";
List.class
的类型为Class<List>
;它不是Class<List<Whatever>>
的子类型/超类型,因此两种类型之间的直接转换是非法的。
可以说Class<List<Integer>>
不存在 - List
只有一个类; List<Integer>
没有这样的类(在运行时它真的只是List
)
然而,这是Java类型系统的缺陷;在实践中,我们确实需要Class<List<Integer>>
之类的东西。我们的解决方案 - 铸造和假装Class<List<Int>>
退出 - 同样存在缺陷 - 但这不是我们的错。