使用泛型创建集合对象

11
当我尝试像下面这样创建对象时:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();

语法上哪里出了问题,有人能解释一下吗?

6个回答

20

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

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

在赋值语句的最左边,Map 可以“变成”一个被赋值的 HashMap,但是同样的规则不适用于出现在泛型参数中的任何类型。

编辑:

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

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

注意,这种语法不允许向地图中添加条目,但作为一种类型传递给方法时很有用。

一些参考资料:


3
你也可以使用Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>(); - Keppil

10

这是类似的错误

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

泛型参数类型应该在两端是相同的。没有继承(IS-A)的概念。如果你仍然想使用它,请使用通配符(?)和extend/super关键字,该关键字只能放在等号左侧。

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

但是

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

如果有人尝试添加扩展Animal类的Cat对象,它将在后面失败并抛出异常。

animal[1] = new Cat();  //compiles fine but throws java.lang.ArrayStoreException at Runtime.
记住animal[1]animal[index]持有Dog的引用。因此,Dog引用变量可以引用Dog对象而不是Cat对象。

为了避免这种情况,JSL在范型列表/集合中做出了这样的更改。 这个答案也适用于你的问题(Map)。
参数化类型应该在两端都是同一类型。

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

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


3
你需要类似这样的东西:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
myMap.put(1, new HashMap<String, Integer>());

3

Map<String, Integer>不同于HashMap<String, Integer>,这就是问题所在。

实际上,HashMap实现了Map接口,因此左侧应该是? extends Map<String, Integer>


2

试试这个:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接