带有泛型的Java编译器错误

时间:2012-10-24 21:45:49

标签: java eclipse generics

我使用此代码收到编译器错误:

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[]>)"

这对我没有意义,因为String []实际上是一个Object,并且与set()中的参数完全兼容。

在我从JDK 1.6升级到1.7之前,我的代码中没有显示此错误。我没有看到Eclipse中的开关将其关闭。如何编译此代码?

编辑:

如果我使用中间变量,它会编译,并删除泛型:

Map anotherMap = myMap;
set(anotherMap);

4 个答案:

答案 0 :(得分:5)

泛型继承与我们对OO继承的常规理解不同。请阅读此tutorial

要编译代码,您可能需要更改方法语法,如下所示:

void set(Map<String, ?> foo) { }
编辑:正如dasblinkenlight评论的那样,如果您有任何计划在set方法中对Map进行修改,除非您定义了具体的类型,否则它将无法工作。

答案 1 :(得分:1)

虽然String[]实际上是Object,但这与Map<String,String[]>实际上是Map<String,Object>并不相同:协方差仿制药不存在。

更改声明

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

使用通配符

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

将使您的代码编译,并尝试从foo地图获取内容将起作用:

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

但是,尝试向地图添加内容会失败:

<击>     Object blah = foo.put(“key”);

由于将地图放在地图中似乎是您的方法的目标(毕竟,必须有一个原因,您称之为set),如果没有指定确切的话,您将无法使其工作类型。

答案 2 :(得分:0)

在泛型中使用类型参数时,继承不会以相同的方式工作。

这是一个过于简化的一般经验法则:

在声明和初始化通用对象时,<>内的内容必须完全匹配。

答案 3 :(得分:0)

也许,Eclipse确实编译了你的代码,因为它是编译器错误。

您需要将set的签名更改为set(Map<String, ?>)才能进行编译。

它在第二种情况下用警告编译,不是吗?这是因为你使用原始地图(没有泛型)来绕过类型安全检查。