我正在尝试使用ConcurrentSkipListMap
创建地图地图。如果我创建一个简单的地图示例,它似乎很好:
Map<Integer, Integer> mmap2 = new ConcurrentSkipListMap<Integer, Integer>();
尝试创建地图地图后,出现Incompatible types
错误:
Map<Integer, Map<Integer, Integer>> mmap =
new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>();
如果我将定义切换为包含ConcurrentSkipListMap
,则其编译没有问题:
Map<Integer, ConcurrentSkipListMap<Integer, Integer>> mmap =
new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>();
为什么我无法使用Map
界面定义地图的地图?
答案 0 :(得分:2)
我可以用一个例子回答这个问题。
Map<Integer, Map<Integer, Integer> mmap = new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>();
mmap.put(5, new HashMap<Integer, Integer>());
在这种情况下,您是否希望允许使用汇总线?如果不允许,则会破坏mmap的定义。如果允许则会打破右侧。
您已经生成了一行代码,无论它是否有效都会给您带来矛盾。因此,我们不允许对mmap进行此类定义。
答案 1 :(得分:0)
继承不适用于Generics type parameters
你可以使用如下的外卡。
Map<Integer, ? extends Map<Integer, Integer>> mmap = new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>();
更多信息阅读java subtyping
答案 2 :(得分:0)
Polymorphism
的概念并没有像对类那样扩展到Java泛型。这就是为什么ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>
不被视为Map<Integer, Map<Integer, Integer>>
的子类型,因此无法分配。
原因是因为 generics 仅提供编译时类型的安全性。在运行时,由于所谓的类型擦除,通用类型是未知的。所以,基本上编译器试图阻止这个
// if this was allowed
List<Shape> shapes = new ArrayList<Circle>();
// and some place else in your code
shapes.add(new Square()); // Square now fits in a Circle list
这会破坏ArrayList
的泛型类型并且不会抛出任何错误;因为,类型是有效的,哪些不是,在运行时是不知道的。但是,如果你说,“嘿,这就是我想要的!Square
进入Shape
s列表。”然后使用{{1}定义列表并且编译器符合。
所以,你只需要将你的作业命名为
new ArrayList<Shape>()
即。更喜欢在使用泛型时使用两侧一致的接口。
编辑 :(回应@ PaulBellora的downvote)
您可以将Map<Integer, Map<Integer, Integer>> mmap =
new ConcurrentSkipListMap<Integer, Map<Integer, Integer>>();
分配给Circle[]
而不是Shape[]
分配给ArrayList<Circle>
。并且,原因是如果您的代码尝试通过ArrayList<Shape>
引用向Square
添加Circle[]
,那么您将在运行时获得Shape[]
,因为JVM会知道数组的实际类型。
但是,由于类型擦除,相同的运行时类型安全性无法扩展到集合,因此泛型类型不是共变体。如果问题是为什么类型被删除,那么如果在运行时知道它可以明显地带来好处;答案是与Java 5之前的代码库配合使用。
答案 3 :(得分:-1)
你可以在这里尝试这个,你将在Map对象中有Map引用
public class GenericTest {
void fun(){
Map<Integer, Map<Integer, Integer>> mmap = new HashMap<Integer, Map<Integer, Integer>>();
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
mmap.put(5,map);
}
}