2

我正在尝试使用ConcurrentSkipListMap. 如果我创建一个简单的地图示例,它似乎很好:

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

一旦我尝试创建地图地图,就会出现Incompatible types错误:

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

如果我将定义切换为包含 a ConcurrentSkipListMap,则其编译没有问题:

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

Map为什么我不能使用界面定义地图的地图?

4

4 回答 4

3

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

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

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

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

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

于 2013-08-28T12:39:10.777 回答
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进入Shapes 列表。” 然后定义这样使用的列表new ArrayList<Shape>()编译器会遵守。

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

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

即在使用泛型时更喜欢使用双方一致的接口。

编辑:(回应@PaulBellora 的反对票)

Circle[]您可以分配 a toShape[]但不能分配ArrayList<Circle>to是有原因的ArrayList<Shape>。而且,原因是如果您的代码尝试通过引用将 a 添加Square到 a中,您将在运行时得到 a,因为 JVM 会知道数组的实际类型。Circle[]Shape[]ArrayStoreException

但是,由于类型擦除,相同的运行时类型安全不能扩展到集合,因此泛型类型不是协变的。如果问题是为什么要删除类型,那么如果在运行时知道它显然会带来好处;答案是使用 Java 5 之前的代码库。

于 2013-08-28T12:42:26.133 回答
0

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

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

更多信息阅读java 子类型

于 2013-08-28T12:31:16.743 回答
-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);
    }
}
于 2013-08-28T13:37:54.983 回答