简体   繁体   中英

Java compiler error with generics

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);

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.

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.

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.

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.

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