当我尝试创建如下对象时:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();
语法上有什么问题,有人可以解释一下吗?
当我尝试创建如下对象时:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();
语法上有什么问题,有人可以解释一下吗?
泛型不是协变的。您可以使用:
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>>();
请注意,此语法不允许将条目添加到映射中,但可用作传入和传出方法的类型。
一些参考资料:
这是类似的错误
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>();
尝试这个
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
你需要这样的东西:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
myMap.put(1, new HashMap<String, Integer>());
Map<String, Integer>
不一样HashMap<String, Integer>
。那就是问题所在。
实际上 HashMap 实现了 Map 接口。所以它应该? extends Map<String, Integer>
在左侧
尝试这个:
Map<Integer, HashMap<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();