11

当我尝试创建如下对象时:

Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

语法上有什么问题,有人可以解释一下吗?

4

6 回答 6

20

泛型不是协变的。您可以使用:

Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
^                                                                ^
--------------^------------------- becomes ------^               |
              -----------------must remain as type ---------------

虽然Map赋值的左外侧可以“变成” aHashMap赋值,但同样不能应用于作为泛型参数出现的任何类型。

编辑:

正如@Keppil 所述,您可以使用有界通配符语法:

Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

请注意,此语法不允许将条目添加到映射中,但可用作传入和传出方法的类型。

一些参考资料:

于 2013-04-12T09:58:07.107 回答
10

这是类似的错误

List<Animal> list = new ArrayList<Dog>();

参数化类型在两端应该是相同的类型。没有继承 (IS-A) 概念。如果您仍想使用它,请使用带扩展/超级关键字的通配符(?),该关键字仅允许在等号的左侧使用。

List<Animal> list = new ArrayList<Dog>(); // is not allowed

Animal[] animal = new Dog[10];  //is allowed
animal[0] = new Dog(); // is allowed

Cat如果有人试图添加(扩展动物)对象,它稍后会失败并抛出异常。

animal[1] = new Cat();  //compiles fine but throws java.lang.ArrayStoreException at Runtime.

记住animal[1]或者animal[index]是抱着reference狗。所以Dog引用变量可以引用Dog对象而不是Cat对象。

所以为了避免这种情况,JSL 在泛型列表/集合中做了这样的改变。此答案也适用于您的问题(Map)。
参数化类型在两端应该是相同的类型。

List<Animal> list = new ArrayList<Animal>(); 
于 2013-04-12T09:57:30.957 回答
6

尝试这个

Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

用一个更简单的例子解释起来更容易

Set<Number> set = new HashSet<Integer>();

是不允许的,因为这样你就可以向整数的 HashSet 添加一个 Double

set.add(1.0)

注意

Set<? extends Number> set = new HashSet<Integer>();

null除了添加到集合之外,不允许添加任何内容。但你只能从中读取数字

您可以在这里找到更多信息http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

于 2013-04-12T09:59:07.543 回答
3

你需要这样的东西:

Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
myMap.put(1, new HashMap<String, Integer>());
于 2013-04-12T09:58:56.697 回答
3

Map<String, Integer>不一样HashMap<String, Integer>。那就是问题所在。

实际上 HashMap 实现了 Map 接口。所以它应该? extends Map<String, Integer>在左侧

于 2013-04-12T10:03:01.577 回答
2

尝试这个:

Map<Integer, HashMap<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();
于 2013-04-12T09:58:29.943 回答