0

I'm getting a compiler error with this code:

Map<String, String[]> myMap;

void set(Map<String, Object> foo) { }

set(myMap); // generates error

Error: "The method set(Map<String,Object>) in the type XXX is not applicable for the arguments (Map<String,String[]>)"

This makes no sense to me, because String[] is in fact an Object, and is entirely compatible with the parameter in set().

This error did not show up in my code until I upgraded from JDK 1.6 to 1.7. I do not see a switch in Eclipse to turn it off. How do I get this code to compile?

Edit:

It does compile if I use an intermediate variable, and drop the generics:

Map anotherMap = myMap;
set(anotherMap);

4 Answers 4

5

Generics inheritance is different from our regular understanding of OO inheritance. Please read this tutorial.

To make your code compile, you may need to change your method syntax like below:

void set(Map<String, ?> foo) { }

EDIT: As dasblinkenlight commented, if you have any plans to do modifications to the Map inside the set method, it won't work unless you have concrete type defined.

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

2 Comments

The Map<String,?> will not work, but merely compile. As soon as the method tries to put anything into foo, the compiler will complain.
To round things out, think what would happen if that did work. Within the set method, you have a Map<String, Object> so you happily call map.put("foo", new SomeObject()). Now myMap, though it's typed such that the values are of String[], has a value of SomeObject.
1

Although String[] is in fact an Object, that is not the same as saying that Map<String,String[]> is in fact a Map<String,Object>: the covariance of generics is not there.

Changing the declaration

void set(Map<String,Object> foo) { }

to one with wildcard

void set(Map<String,?> foo) { }

will make your code compile, and attempts to get things from the foo map will work:

Object blah = foo.get("key");

However, attempts to add things to the map would fail:

Object blah = foo.put("key");

Since putting things in the map appears to be the goal of your method (after all, there must be a reason why you called it set) you wouldn't be able to make it work without specifying the exact type.

Comments

0

When you use type parameters in generics, inheritence does not work the same way.

Here's an over-simplified general rule of thumb:

The stuff inside the <>s must match exactly when declaring and initializing generic objects.

Comments

0

Perhaps, Eclipse did compiled your code because of it's compiler bug.

You'll need to change signature of set to set(Map<String, ?>) to make it compile.

It compiles in 2nd case with a warning, isn't it? It's because you use raw Map (w/o generics) to circumvent type-safety check.

Comments

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.