在Java中,在generics类型的实例上调用getClass时如何避免原始类型?

假设我在Java中有这个:

List list = new ArrayList(); list.getClass(); 

最后一个表达式的类型是Class Class 。 我理解为什么,由于擦除,它不能是Class<? extends List> Class<? extends List> 。 但为什么不能成为Class<? extends List> Class<? extends List>

如果我想将这个表达式的结果分配给一个变量,以某种方式保存这个类实际上是某种List的信息,我是否有办法避免未经检查的强制转换警告原始类型警告

 Class listClass = list.getClass(); // raw type warning Class<? extends List> listClass = (Class<? extends List>) list.getClass(); // unchecked cast warning 

首次引入generics时, getClass返回Class Class ,其中X是调用它的表达式的静态类型。 这种行为导致了不合理的编译问题,正如此Oracle错误中所报告的那样。 这是bug报告的例子:

以下程序片段无法编译

 void f(List li, List ls) { if (li.getClass() == ls.getClass()) ; } 

因为Class>Class>的交集是空的。

通过将getClass的返回类型扩展为现在的问题来解决此问题。 从文档 :

实际的结果类型是Class Class where |X| 是擦除调用getClass的表达式的静态类型。

这解决了上述问题,但因此导致了您的问题指出的问题。 不久之后,报告了另一个错误 ,争论如下:

我认为getClass()类型规则可以更改为Class Class

通配符操作定义如下:如果T是参数化的,则wildcard(T)=erasure(T)否则, wildcard(T)=T

理由:

  1. 此规则引入原始类型。 原始类型必须仅用于与遗留代码交互。

  2. 新规则引入了通配符。 参数化类型和通配符之间的关系基于子类型规则。 参数化类型和通配符之间的关系基于原始类型转换。

这个错误没有采取行动,至今仍未解决,并提出以下抗议:

该提议意味着getClass()将返回一个Class> Class>对象,它与其他Class>不兼容 Class>对象。 这与现有代码兼容:

 List l = ...; Class c = l.getClass(); 

因为新型的RHS, Class> Class> ,是Class的子类型Class Class

丰富Class类型参数的一个缺点是它会破坏Class.cast习惯用法。 今天你可以写:

 List x = ...; Class cl = x.getClass(); List y = cl.cast(null); 

并且在cast()处获得警告,因为从ListList的未经检查的转换。 但是根据提案,类似的代码不能编译:

 List x = ...; Class> cl = x.getClass(); List y = cl.cast(null); 

因为cast()返回的List无法转换为List 。 避免错误的唯一方法是将cl.cast(..)强制转换为List ,并将未经检查的转换警告置于List 。 这实际上就是getClass()已经做到的。

总体而言,该提案似乎是一个好主意,但它具有中等复杂性和相当小的收益。

(删节并纠正了一些拼写错误)

由于List是一个接口,我不确定是否有可能发现List接口是为ArrayList实现的。 在这里找到这个可能有帮助的链接。

我确实搞砸了一下,发现……

  Class d = list.getClass(); d.equals(ArrayList.class); 

但我不确定这是不是你要找的……

祝好运!