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>());

この場合、プットラインが許可されると思いますか? 許可されていない場合は、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これはのジェネリック型を破壊し、エラーをスローしません。どのが有効で、どの型が有効でないかは、実行時にはわからないためです。しかし、「ねえ、それが私がしたいことです! s のSquareリストに入りたい」と言ったら。Shape次に、使用するnew ArrayList<Shape>()コンパイラが準拠するようにリストを定義します。

したがって、次のように割り当てを行う必要があります

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

つまり、ジェネリックを使用しながら、両側で一貫したインターフェイスを使用することを好みます。

編集:(@PaulBelloraの反対票に応じて)

Circle[]に を割り当てられるのに に割り当てられShape[]ないのArrayList<Circle>には理由がありますArrayList<Shape>。その理由は、コードが参照を介して aSquareに aを追加しようとすると、JVM が配列の実際の型を認識しているため、実行時に が取得されるためです。Circle[]Shape[]ArrayStoreException

ただし、型の消去により、同じランタイム型の安全性をコレクションに拡張することはできません。したがって、ジェネリック型は共変ではありません。問題がなぜタイプを消去したのかということだった場合、実行時にそれを知っていると明らかにメリットがあるかどうか。答えは、Java 5 より前のコード ベースをうまく利用することです。

于 2013-08-28T12:42:26.133 に答える