用于泛型类型的Java转换“.class”-operator,例如列表,到“Class <list <?>&gt;”和“Class <list <integer>&gt;”</list <integer> </list <?>

时间:2011-09-21 15:14:28

标签: java generics reflection casting

我使用.class - 运算符向泛型类提供有关包含类型的信息。对于非通用包含类型,例如Integer.class,这没有任何问题。但是所包含的类型是通用的,例如List<Integer>.classList.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);

为什么tListInt2tListGeneric的声明会给出错误? 为什么使用tListInt3进行向上转换然后向下转换不会产生错误? 是否有更好的方式来声明tListInt3

亲切的问候,
Kasper van den Berg

PS。如果您希望将代码视为需要此类型信息的外部通用容器,请告诉我们。如果需要,我会发布它。

1 个答案:

答案 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>>退出 - 同样存在缺陷 - 但这不是我们的错。