当我尝试按如下方式创建对象时:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();
语法上有什么问题,任何人都可以解释一下吗?
答案 0 :(得分: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>>();
请注意,此语法不允许将条目添加到地图中,但可用作要传递给方法和从方法传递的类型。
一些参考文献:
答案 1 :(得分: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
如果有人试图添加Cat
(扩展Animal)对象,它将在以后失败并抛出异常。
animal[1] = new Cat(); //compiles fine but throws java.lang.ArrayStoreException at Runtime.
请记住 animal[1]
或 animal[index]
持有Dog reference
。因此Dog
引用变量可以引用Dog
对象而不是Cat
对象。
为了避免这种情况,JSL在泛型列表/集合中进行了这样的更改。此答案也适用于您的问题(Map
)。
参数化类型在两端应该是相同的类型。
List<Animal> list = new ArrayList<Animal>();
答案 2 :(得分:6)
试试这个
Map<Integer, ? extends Map<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();
在更简单的例子中解释更容易
Set<Number> set = new HashSet<Integer>();
是不允许的,因为那时你可以添加Double到HashSet of Integers
set.add(1.0)
请注意
Set<? extends Number> set = new HashSet<Integer>();
不允许在集合中添加除null
之外的任何内容。但你只能从中读取数字
您可以在此处找到更多信息http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html
答案 3 :(得分:3)
你需要这样的东西:
Map<Integer, Map<String, Integer>> myMap = new HashMap<Integer, Map<String, Integer>>();
myMap.put(1, new HashMap<String, Integer>());
答案 4 :(得分:3)
Map<String, Integer>
与HashMap<String, Integer>
不同。这就是问题所在。
实际上HashMap实现了Map接口。所以它应该在左侧? extends Map<String, Integer>
答案 5 :(得分:2)
试试这个:
Map<Integer, HashMap<String, Integer>> myMap = new HashMap<Integer, HashMap<String, Integer>>();