I have the following code:
public static<F, S> void xyz() {
class Pair<X, Y> {}
class Role<F> {}
Map<?, List<Pair<?, ?>>> map = null;
Role<F> role = null;
List<Pair<F, S>> result = (List<Pair<F, S>>) map.get(role);
}
Unfortunately, Java complains about the cast on the last line. Why does this happen?
In my option, this is counterintuitive. A cast should be allowed in every place where there’s a possibility of a correct type correspondence.
“A cast should be allowed in every place where there’s a possibility of a correct type correspondence.” In this case, there is NO possibility of a correct type correspondence.
An object can never be an instance of both
List<A>andList<B>, if A and B are concrete and not the same, even if A is a subtype of B or whatever. For example, you cannot have an object that is bothList<String>andList<Object>. There is (conceptually) a specific type parameter for each object. You have to understand this part first.Your example is just the same —
List<Pair<F, S>>andList<Pair<?, ?>>. For the same reason as with String and Object above, an object that is of typeList<Pair<?, ?>>can never also beList<Pair<F, S>>.Update: More explanation in case it helps. @Konstantin: If you write
Pair<?, ?>, then those type parameters at the top level, which are?(wildcards), are flexible.Pair<T1, T2>is compatible withPair<?, ?>. However, inList<Pair<?, ?>>, the?is not at the top level. The type parameter at the top level isPair<?, ?>, which is not a wildcard, and thus is not flexible. It doesn’t matter that you happen to have?deeper down. If you haveList<? extends Pair<?, ?>>, then the top level is a wildcard, and is flexible.What you probably want is
List<? extends Pair<?, ?>>. Perhaps it will help you to consider the difference betweenList<Pair<?, ?>>andList<? extends Pair<?, ?>>.List<Pair<?, ?>>says that this is a List, and it type parameter is exactly the typePair<?, ?>(and nothing else, notPair<T1, T2>, etc.).List<? extends Pair<?, ?>>says that this is a List, and it type parameter is something which is a subtype ofPair<?, ?>(and this includesPair<T1, T2>).