Why does trying to compile
public class GenericsFail {
public static void main(String[] args) {
accept(new HashMap<String, List<String>>());
}
public static void accept(Map<String, List<?>> multiMap) {}
}
give the error
GenericsFail.java:7: error: method accept in class GenericsFail cannot be applied to given types;
accept(new HashMap<String, List<String>>());
^
required: Map<String,List<?>>
found: HashMap<String,List<String>>
reason: actual argument HashMap<String,List<String>> cannot be converted to Map<String,List<?>> by method invocation conversion
The wildcard is only allowed if it’s not nested inside List.
The reason is that the
?inList<?>could be “anything”, but a different “anything” in eachMapentry. That is, it would accept aList<String>in one entry, and aList<Integer>in another.But you are passing in a
Mapthat has the same type ofListin every entry, so the type is not bound in the same way or the to same degree for freedom.The “fix” is to lock the type to a specific type, but still being “anything” – just the same “anything* in every entry, by typing the method:
or if your method really doesn’t need to know which type, use a wildcard to wrap the type:
This last version works because the type of the list, although being a wildcard, is fixed to an unknown, but consistent, type when called.
I find the typed version easier to read (and code), and the type is there for use should you decide later that your method needs to know the type.