简体   繁体   English

泛型的Java编译器错误

[英]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(). 这对我来说毫无意义,因为String []实际上是一个对象,并且与set()中的参数完全兼容。

This error did not show up in my code until I upgraded from JDK 1.6 to 1.7. 从我的JDK 1.6升级到1.7之前,该错误没有显示在我的代码中。 I do not see a switch in Eclipse to turn it off. 我没有在Eclipse中看到将其关闭的开关。 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. 泛型继承不同于我们对OO继承的常规理解。 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. 编辑:正如dasblinkenlight所评论的,如果您有任何计划对set方法中的Map进行修改,则除非您定义了具体的类型,否则它将无法工作。

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. 尽管String[]实际上是一个Object ,但这与说Map<String,String[]>实际上是Map<String,Object>并不相同:泛型的协方差不存在。

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: 将使您的代码编译,并尝试从foo映射中获取内容将起作用:

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

However, attempts to add things to the map would fail: 但是,尝试将内容添加到地图将失败:

Object blah = foo.put("key"); 对象等等= 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. 由于将事物放入地图中似乎是您方法的目标(毕竟,一定有理由将其称为set ),因此,如果不指定确切的类型,就无法使其工作。

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. 也许是因为它的编译器错误,Eclipse确实编译了您的代码。

You'll need to change signature of set to set(Map<String, ?>) to make it compile. 您需要将set签名更改为set(Map<String, ?>)以进行编译。

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. 这是因为您使用原始Map(不带泛型)来规避类型安全性检查。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM