尝试创建地图地图时,不兼容的类型错误

时间:2013-08-28 12:28:29

标签: java generics map concurrentskiplistmap

我正在尝试使用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界面定义地图的地图?

4 个答案:

答案 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);
    }
}