Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem using generic map with wildcard

I have a method that returns a map defined as:

public Map<String, ?> getData();

The actual implementation of this method is not clear to me, but, when I try to do:

obj.getData().put("key","value")

I get following compile time error message:

The method put(String, capture#9-of ?) in the type Map is not applicable for the arguments (String, String)

What is the problem? Is String not of type anything?

Thanks in advance.

like image 976
mmoossen Avatar asked Dec 17 '09 11:12

mmoossen


People also ask

How do you use generic wildcards?

The question mark (?) is known as the wildcard in generic programming. It represents an unknown type. The wildcard can be used in a variety of situations such as the type of a parameter, field, or local variable; sometimes as a return type.

What are wildcards arguments in generics?

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).

Can HashMap use generic types?

The term generic simply is the idea of allowing the type (Integer, Double, String, etc. or any user-defined type) to be the parameter to methods, class, or interface. For eg, all the inbuilt collections in java like ArrayList, HashSet, HashMap, etc. use generics.

What is the difference between generics and wildcards in Java?

Wildcards are nothing but the question mark(?) that you use in the Java Generics. We can use the Java Wildcard as a local variable, parameter, field or as a return type. But, when the generic class is instantiated or when a generic method is called, we can't use wildcards.


2 Answers

The return type of

Map<String, ?>

is the same as

Map<String, ? extends Object>

The means that the concrete type returned could be a Map<String, AnyClass>. You can't put a String into an AnyClass, hence the error.

A good general principle is to not use wildcards in method return types.

like image 199
Ben Lings Avatar answered Nov 16 '22 01:11

Ben Lings


The wildcard means "the value type parameter could be anything" - it doesn't mean "you can use this as if it were anything you want it to be". In other words, a Map<String, UUID> is valid as a Map<String, ?> - but you wouldn't want to be able to put a String value into it.

If you want a map which can definitely accept string values, you want:

Map<String, ? super String>
like image 35
Jon Skeet Avatar answered Nov 16 '22 00:11

Jon Skeet