java.lang.Classgenerics和通配符

为什么以下代码无法编译?

interface Iface { } class Impl implements Iface { } class TestCase { static Class<? extends Iface> clazz = Impl.class; } 

错误是

java:不兼容的类型: java.lang.Class无法转换为java.lang.Class<? extends Iface> java.lang.Class<? extends Iface>

但我不明白为什么通配符不能捕获。

这里的子类型关系是:

  Class ╱ ╲ Class> Class 

(我在回答‘无法从List转换为List> ‘时解释了这一点 。)

所以基本上它不会编译,因为它是一个横向转换。

如果有可能,你可以进行我在那里描述的投射:

 (Class>)(Class)Impl.class 

如果你不能进行演员表演,那么你可能只需处理一个原始的有界Class Class 。 它主要是因为警告而烦人,但它开启了出错的可能性:

 interface Iface { void accept(T a); } class Impl2 implements Iface { public void accept(String a) { } } class TestCase { static Class clazz = Impl2.class; public static void main(String[] args) throws Exception { // throws ClassCastException clazz.newInstance().accept(new Object()); } } 

不太可能发生,但这取决于你在做什么我想。


我倾向于认为这是Java类型系统的问题。

  • 可能应该有一个类型参数的特殊规则? extends T ? extends T包含一个类型参数? extends T ? extends T使得例如一个Class Class转换为Class> Class> 。 从定义子类型的现有方式( TT的超类型)的角度来看,这没有意义,但从类型安全的角度来看它是有意义的。

  • 或者例如List.class应该是Class>而不是Class

  • 或者其他一些比我更聪明的聪明人可以想到。

我上面描述的ClassCastException的有趣之处在于它完全是人为的。 实际上,使用未经检查的强制转换防止它会导致警告。

我想,只是表明Java中的generics尚未完成。

由于类型擦除 ,当你说Impl.class你得到一个Class 。 也就是说,你可以说

 Class clazz = Impl.class; 

generics是编译时类型安全function。