Reputation: 308
I hava a list:
List<Map<String, Integer>> list = new ArrayList<>();
and a method:
public void doSth(List<Map<String, ?>> list) {
}
calling it like this:
doSth(list);
shows this error:
incompatible types: java.util.List<java.util.Map<java.lang.String,java.lang.Integer>> cannot be converted to java.util.List<java.util.Map<java.lang.String,?>>
However, this works:
public <V> void doSth(List<Map<String, V>> list) {
}
What's the difference butween ?
and V
?
Upvotes: 0
Views: 175
Reputation: 178253
Java treats type parameters that are embedded in within other type parameters differently from just plain old type parameters. Specifically, because Java's generics are invariant, any type parameters embedded must either match exactly or you may have to throw in a ? extends
to satisfy the compiler's compile-time type safety requirement.
When the method expects a List<Map<String, ?>>
, it's a list of maps that map strings to some specific yet unknown type, which may not be Integer
. The map may use any object type.
When you declare V
, the compiler resolves V
to Integer
so that an exact match to the method is made.
You can also do one of the following: Use a wildcard in the declaration of list
:
List<Map<String, ?>> list = new ArrayList<>();
or insert a ? extends
so the method can expect a subtype and not necessarily the exact match with regard to generics:
public static void doSth(List<? extends Map<String, ?>> list) {
}
or you can just match Integer
for Integer
:
public static void doSth(List<Map<String, Integer>> list) {
}
Upvotes: 1