Found fact about unbounded wildcards that is annoying me. For example:
public class Test {
private static final Map
It is important to understand the implication of the wildcard types.
You already understood that you can assign your Map
to Map, ?>
as Map, ?>
implies arbitrary types, unknown to whoever might have a reference of the declared type Map, ?>
. So you can assign any map to Map, ?>
.
In contrast, if you have a Map, Map, ?>>
it has an unknown key type but the value type is not unknown. It’s Map,?>
the type, recall the information above, that can be assigned with any map.
So, the following code is legal:
Map, Map, ?>> map=new HashMap<>();
map.put(null, Collections.singletonMap("foo", "bar"));
map.put(null, Collections.singletonMap(42.0, 1000));
map.put(null, Collections.
Here, we are putting a null
key as we can’t put
anything else for keys but arbitrary typed maps as values as that’s what a value type of Map, ?>
implies: can be assigned from arbitrary maps. Note that by iterating over the entries we can also set other entries having non-null
keys to arbitrary maps then.
So I’m quite sure that you don’t want to assign your Map
to a Map, Map, ?>>
and discover arbitrary maps not being Map
as values afterwards and that you are quite happy that the compiler doesn’t allow this.
What you actually want to do is to assign your map to a type which has both, key and value type, unknown but still telling that your values are maps:
Map> someMap = new HashMap<>();
Map, ? extends Map, ?>> map=someMap;
In the generic type system Map
is a sub-type of Map, ?>
so you can assign it to Map, ?>
as well as ? extends Map, ?>
. This sub-type relationship is not different than the relationship of String
to Object
. You can assign any String
to a variable of type Object
but if you have a Map,String>
you can’t assign it to Map,Object>
but only to Map, ? extends Object>
for the same reason: the map shall continue to contain String
s as values rather than receiving arbitrary objects.
Note that you can workaround this limitation. You can say:
Map> someMap = new HashMap<>();
Map, Map, ?>> map=Collections.unmodifiableMap(someMap);
Since the map returned by unmodifiableMap
does not allow any modifications, it allows widening the key and value types. The contained values are of the specified type (i.e. Map, ?>
) when you query the map, but attempts to put in arbitrary map values, while not rejected by the compiler, will be rejected at runtime.