18

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.

1
  • thank you for the answers.. i am impressed of how fast you did react... many thanks Commented Dec 17, 2009 at 12:34

5 Answers 5

18

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.

Sign up to request clarification or add additional context in comments.

Comments

13

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>

2 Comments

String class is final, so just Map<String, String>
@nybon Suppose you have class A extends Map<String, String> and class B extends Map<String, Object>, you want to write a method that can take either class A or class B as argument. That's when you need Map<String, ? super String>
6

Map<String, ?> is a short form of Map<String,? extends Object> and doesn't mean that anything can be added as value. It says that the Map-object can have any generic value type extending Object.

This means that the Map object can be a HashMap<String, String> or a HashMap<String, Integer> as well. Because the compiler can't check which value types will be accepted, he won't let you call methods with the value type as a parameter.

Note:

  • You can call methods with the value type as a return value, because everything must extend Object (? extends Object)
  • A Map<String, ? super String> will have the opposite effect: You can always use a String as parameter, but the return-type is unclear.

Comments

0

Try this:

public Map<String, Object> getData();

Comments

-2

[EDIT] This is really wrong... I understood.

My first answer was:

That's java : String is not an object.

Try with

obj.getData().put("key",new String("value"));

But String extends Object... while I thought String was a primitive. I learned something ^^

7 Comments

A string certainly is an object. What precise difference do you believe it would make to call the String constructor explicitly in this case?
String is not a primitive type, is it?
No, it's not a primitive type... so why did you claim it's not an object?
I believed it was a primitive, like a almost object... Mistaken! But what is the difference between my thought and Ben Lings one?
Ben Lings' answer is completely different, and accurate. What do you think the similarity is between your answer and Ben's?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.