キャストは安全ではありませんU
。なぜならextendsはありますが、 (必ずしも) extendsの場合Foo<String>
ではないからです。実際、はそれらが同じものである場合、つまり が である場合にのみ拡張されます。Bar<U>
Bar<Foo<String>>
Bar<U>
Bar<Foo<String>>
U
Foo<String>
直観的には、(たとえば)List<String>
は のサブタイプであるべきだと思われるかもしれList<Object>
ませんが、これはジェネリックの仕組みではありません。List<String>
は のサブタイプですが、 のサブタイプではList<? extends Object>
ありませんList<Object>
。(次のような例を検討する方がより理にかなっているかもしれませんComparable<T>
。 :Comparable<String>
は " を any と比較できることを意味するString
のに対して、 " は any と比較できることを意味します。が のサブタイプであってはならないことは明らかです。)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;
はunsafestringList
です。これは、ランタイムが (消去のために) キャストをチェックする方法がないためです。したがって、間違っていても例外はスローされませList<String>
んInteger
。(何が起こるかというと、後で、ClassCastException
その要素で何かをしようとすると自発的に取得できるということです。)