简体   繁体   中英

Generics can't instantiate `new HashMap<String, ?>`. Why?

Why does the following line of code give an error in HashMap? It is not taking the wild card in the right hand side of the assignment.

Map<String,?> map=new HashMap<String,?>();

You can't instantiate a parameterized type like that. A wildcard parameterized type is not a concrete type, so they could not appear in a new expression.

A wildcard parameterized type denotes a family of types comprising concrete instantiations of a generic type. The kind of the wildcard being used determines which concrete parameterized types belong to the family.

So, Map<String,?> denotes the family of types, which can be Map<String, Object> , Map<String, String> , anything. You have to use the concrete type while creating an actual map.

So, you can do:

Map<String,?> map=new HashMap<String, String>();
Map<String,?> map=new HashMap<String, Object>();

But the issue with this declaration is that, you can't add anything to map except null .


On the other hand, consider other types of wildcard - upper bounded , and lower bounded .

Upper Bounded Wildcard :

Map<String, ? extends Number>

The family of types denoted by this type are the concrete instantiation, where the value type is either Number , or a subtype of Number . So, for this one, the following are valid creation of concrete parameterized type:

Map<String, ? extends Number> map = new HashMap<String, Number>();
Map<String, ? extends Number> map = new HashMap<String, Integer>();

But again, issue here is you can't add anything in the map except null or the value previously fetched from it.


Lower Bounded wildcard :

Map<String, ? super Integer>

As you already know, you can't add anything to the wildcard parameterized type with unbounded wildcard, or upper bounded wildcard. There is a third type - lower bounded wildcard, which can be used if you are going to add something to the map. The family of type for the above parameterized type are the one that takes value of type Integer or it's super type. So, you can instantiate it like this:

Map<String, ? super Integer> map = new HashMap<String, Number>();
Map<String, ? super Integer> map = new HashMap<String, Integer>();
Map<String, ? super Integer> map = new HashMap<String, Serializable>();

But there is another issue here. Although you can add a value to it, but when you fetch some value, you cannot be sure what type you get.


So, depending upon your requirement, you may have to use one or the other type of wildcard. May be some more information in the question might help you. But, in general just remember, you can't create an object of wildcard parameterized type, but only concrete parameterized type.

实例化具体类的对象时,不能使用通配符。

Just do:

class SuperBogusUnrelatedClass {}
// ...
Map<String, ?> map = new HashMap<String, SuperBogusUnrelatedClass>();

The above is correct, and 100% type-safe. Seriously, you can just put anything in there, even Math . Why is it correct? Since it's a wildcard, it means it can be anything; you don't know what it is.

The ridiculousness of the above example also shows why this initialization is pretty much completely useless -- since the type parameter is unknown, you can't safely put any values (except null ) into the Map<String, ?> . So your Map will either have to be empty, or filled with entries whose value is null . So basically, it is equivalent to a Set .

由于要创建HashMap对象,因此必须指定所有通用参数。

In Java 7 and later you could just used the diamond notation as mentioned here:

https://docs.oracle.com/javase/tutorial/java/generics/types.html#diamond

Here's a quick example of using the diamond derived from the line of code shown in the question:

Map<String,?> map=new HashMap<>();

You are instantiating an object by whose type is a type parameter.It is not possible.

More details Can I create an object whose type is a type parameter?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM