2

I'd like to use a map with various lists as values :

Map<String, List<Integer>> ml;
Map<String, ?> ml2 = ml; // OK
Map<String, List<?>> ml3 = ml; // Type mismatch

Why is the last line not valid?

jaudo
  • 2,022
  • 4
  • 28
  • 48
  • A `Map>` is a map into which you can put a string and a list of anything. A `Map>` is a map into which you can _only_ put a string and a list of integers. – khelwood Oct 20 '16 at 08:50

2 Answers2

7

It's not valid because if it was valid you'd be able to add non-integer lists to ml as well.

Example (not valid):

Map<String, List<Integer>> ml;
Map<String, List<?>> ml3 = ml; 

ml3.put("strings", Arrays.asList("evil","string"));

List<Integer> l = ml.get("strings"); //see how this is going to fail?

Why is Map<String, ?> ml2 = ml; valid? That's because the use of a wildcard tells the compiler to not allow adding new elements, i.e. ml2.put("strings", Arrays.asList("evil","string")); would not be allowed (the compiler doesn't do a type check, it just sees the wildcard and knows you must not call that method.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • I think it would be nice to explain why middle line conversion succeeds in such case (and show you cannot really put anything in it through that reference, so it is safe). Plus it is ml3.put, but ml3.add ;) – Artur Biesiadowski Oct 20 '16 at 08:52
  • @ArturBiesiadowski yes, fixed the typos and added the explanation :) – Thomas Oct 20 '16 at 08:52
  • Thank you, I didn't see the problem this way – jaudo Oct 20 '16 at 08:54
  • Note that it is still possible to add elements to a `Map` - but the only value that can be added is `null` (if the map supports null values). – Hulk Oct 20 '16 at 09:28
-1

Map<String, ?> will take a map of Strings to any object, List of Integer can be matched by this wildcard. However, List of Integer does not match List of ? (List of any object), as List of Integer can only take Integer objects.

dahui
  • 2,128
  • 2
  • 21
  • 40