演员表是不安全的,因为虽然Uextends Foo<String>,它不是(必然)情况是Bar<U>extends Bar<Foo<String>>。事实上,只有当它们是相同的东西时Bar<U>才会扩展Bar<Foo<String>>,即 when Uis 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当您尝试使用该元素做某事时,您会变得自发。)