2013-08-28 61 views
1

我正尝试使用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

这是很有意思的内部地图参考。我本来期望能够工作。 – Cruncher

+0

啊,是的,它是有道理的,它不应该工作。当你创建一个新的ConcurrentSkipListMap >()时,你实际上并没有实例化第二个skiplistmap。因此,您创建的地图不会接受不是跳过列表地图的地图,原始定义必须保证 – Cruncher

+0

[列表列表的子类可能重复?为什么不是Java的泛型隐式多态?](http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicitly-p) –

回答

2

我可以回答用一个例子的问题。

Map<Integer, Map<Integer, Integer> mmap = new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>(); 

mmap.put(5, new HashMap<Integer, Integer>()); 

在这种情况下,您是否希望放置放置线?如果它不被允许,那么它会打破mmap的定义。如果允许的话,它会打破右手边。

你已经产生了一行代码,无论它是否有效,都会给你一个矛盾。因此我们不允许这样定义mmap。

+3

请问downvoter请解释他们的downvote? –

0

继承不适用于泛型type parameters
您可以使用通配符如下。

Map<Integer, ? extends Map<Integer, Integer>> mmap = new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>(); 

更多信息阅读java subtyping

+1

也许是关于为什么是这样的解释,类似于我的评论(但有组织)是为了。 – Cruncher

+1

你将无法添加任何东西到你的'地图'。尝试一下! –

0

Polymorphism的概念不像扩展到类一样扩展到Java泛型。这就是为什么ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>不被视为Map<Integer, Map<Integer, Integer>>的子类型,因此无法分配。

造成这种情况的原因泛型只提供编译时类型安全。在运行时,通用类型由于所谓的类型擦除而未知。所以,基本上编译正试图阻止这种

// 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列表。”然后定义列表,这样使用new ArrayList<Shape>()编译器将符合。

所以,你只需要让你的任务作为

Map<Integer, Map<Integer, Integer>> mmap = 
        new ConcurrentSkipListMap<Integer, Map<Integer, Integer>>(); 

即倾向于使用接口的使两侧相一致,同时使用泛型。

编辑:(针对@ PaulBellora的downvote)

还有一个原因,为什么你可以指定一个Circle[]Shape[]但不ArrayList<Circle>ArrayList<Shape>。原因是,如果你的代码试图通过Shape[]引用将Square添加到Circle[]引用中,你将在运行时得到ArrayStoreException,因为JVM会知道数组的实际类型。

但是,由于类型擦除相同运行时类型的安全不能扩展到集合,因此泛型类型不在同一变种。如果问题是为什么如果在运行时知道它的类型会消失,那么显然会有好处;答案应该是与Java 5之前的代码库很好地搭配。

+1

-1泛型不是协变的原因不是类型删除。 –

+0

@PaulBellora,补充我的回应作为更新。请留下回应,说明你为什么认为你是对的。 –

+0

@TheOtherDownVoter,请留意留下回复。与能够支持他们说话的人会面很愉快。 –

-1

你可以试试这个在这里你将有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); 
    } 
} 
+0

不回答“为什么我不能使用Map接口定义地图的地图?” –

相关问题