演员表是不安全的,因为虽然U
extends Foo<String>
,它不是(必然)情况是Bar<U>
extends Bar<Foo<String>>
。事实上,只有当它们是相同的东西时Bar<U>
才会扩展Bar<Foo<String>>
,即 when U
is Foo<String>
。
直觉上,看起来(例如)List<String>
应该是 的子类型List<Object>
,但这不是泛型的工作方式。List<String>
是 的子类型List<? extends Object>
,但不是的子类型List<Object>
。(考虑这样的例子可能更有意义Comparable<T>
:Comparable<String>
表示“可以与任何比较String
,而Comparable<Object>
表示“可以与任何比较Object
”。应该清楚,Comparable<String>
不应该是 的子类型Comparable<Object>
。)
[…] 演员不会投掷 […],因此演员确实是安全的?
我认为您误解了警告的性质。Eclipse 警告您,即使它应该抛出这个演员表也不会抛出,这实际上就是它不安全的原因。例如,这段代码:
final Object o = Integer.valueOf(7);
final String s = (String) o;
是完全安全的,因为演员表会抛出异常。但是这段代码:
final List<?> wildcardList = new ArrayList<Integer>(Integer.valueOf(7));
final List<String> stringList = (List<String>) wildcardList;
是unsafe,因为运行时无法检查强制转换(由于擦除),所以即使它是错误的,它也不会抛出异常:stringList
现在是 a List<String>
,其第一个元素是 type Integer
。(发生的事情是,在稍后的某个时候,ClassCastException
当您尝试使用该元素做某事时,您会变得自发。)