I'm trying to understand why this code has an unchecked cast warning. The first two casts have no warning, but the third does:
class StringMap<V> extends HashMap<String, V> {
}
class StringToIntegerMap extends HashMap<String, Integer> {
}
Map<?, ?> map1 = new StringToIntegerMap();
if (map1 instanceof StringToIntegerMap) {
StringToIntegerMap stringMap1 = (StringToIntegerMap)map1; //no unchecked cast warning
}
Map<String, Integer> map2 = new StringMap<>();
if (map2 instanceof StringMap) {
StringMap<Integer> stringMap2 = (StringMap<Integer>)map2; //no unchecked cast warning
}
Map<?, Integer> map3 = new StringMap<>();
if (map3 instanceof StringMap) {
StringMap<Integer> stringMap3 = (StringMap<Integer>)map3; //unchecked cast warning
}
This is the full warning for the stringMap3
cast:
Type safety: Unchecked cast from
Map<capture#3-of ?,Integer>
toStringMap<Integer>
However, the StringMap
class declaration specifies the first type parameter of Map
(i.e., String
), and both map3
and the StringMap<Integer>
cast use the same type for the second type parameter of Map
(i.e., Integer
). From what I understand, as long as the cast doesn't throw ClassCastException
(and it shouldn't since there is an instanceof
check), stringMap3
would be a valid Map<String, Integer>
.
Is this a limitation of the Java compiler? Or is there a scenario where calling methods of either map3 or stringMap3 with certain arguments may result in an unexpected ClassCastException
if the warning is ignored?