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.
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.
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).
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.
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.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With