Java 将泛型类型(例如 List)上使用的“.class”运算符转换为“Class<List<?>>”和“Class<List<Integer>>”

2022-09-03 01:04:17

我使用 -运算符向泛型类提供有关所包含类型的信息。对于非泛型包含类型,例如 ,这可以毫无问题地工作。但是,由于包含的类型是泛型,例如 或者它会导致有关类强制转换的编译时错误。.classInteger.classList<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);

为什么声明和给予和错误?为什么上行和下行不产生错误?有没有更好的声明方式?tListInt2tListGenerictListInt3tListInt3

带着亲切的问候,
卡斯帕·范登伯格

ps. 让我知道,如果你喜欢看到需要这种类型信息的外部通用容器的代码;如果需要,我会发布它。


答案 1
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.classClass<List>Class<List<Whatever>>

可以说不存在 - 只有一个类;没有这样的类(实际上只是在运行时)Class<List<Integer>>ListList<Integer>List

但是,这是Java类型系统的一个缺陷;在实践中,我们确实需要这样的东西。我们的解决方案-投射和假装退出-同样存在缺陷-但这不是我们的错。Class<List<Integer>>Class<List<Int>>


答案 2