9

私はジェネリックに慣れていないので、どこが間違っているのかわかりません...

インタフェース Animal を実装する Cat、Dog、Rabbit というクラスがあります。

次のコードはコンパイルされます

Set<? extends Animal> animalSet;
Set<Dog> dogSet = new HashSet<Dog>();
animalSet = dogSet;

しかし、次のコードはそうではありません

Map<String, Set<? extends Animal>> animalMap;
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();
animalMap = dogMap; // this line will not compile

コンパイラは、型に互換性がないと言います。どこが間違っていますか?

アップデート

みんなの助けに感謝

別のワイルドカードを追加して、コードの最初の行を変更しました。次のコードはコンパイルされます

Map<String, ? extends Set<? extends Animal>> animalMap;
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();
animalMap = dogMap;

以下の Cyrille Ka による解決策も参照してください。

4

7 に答える 7

7

基本的に、あなたが書くとき:

Map<String, Set<? extends Animal>> animalMap;

マップの任意の値が、型が Animal のサブクラスである任意のオブジェクトを含むことができるセットであることを宣言します。その場合、クライアント コードを次のように記述することは完全に合理的です。

animalMap.put("miaow", aCatSet);

はどこacatSetですかSet<Cat>

ただし、を値としてdogMap受け入れることはできません。受け入れることしかできません。したがって、型に互換性がない可能性があるため、この構築は禁止されています。Set<Cat>Set<Dog>

編集:それを修正する方法については、何をしたいかによって異なります。dogMapどこかにコンテンツを入れたい場合は、次animalMapのようにコンテンツをコピーするだけです。

Map<String, Set<? extends Animal>> animalMap = new HashMap<String, Set<? extends Animal>>();
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();

/// fill dogMap

animalMap.putAll(dogMap);
于 2013-11-07T15:11:48.103 に答える
3

Java は厳密に型指定されているため、 ? extends Animalis not 、 、または別のサブクラスDogである可能性があります。Cat

例えばこの場合、 と定義すれば、Set<? extends Animal> animalSet合法的に ができますよねanimalSet.add(new Cat())animalSetしかし、これを で初期化したいのですがSet<Dog>、これはもう許可されanimalSet.add(new Cat())ません。これは矛盾しており、これが許可されていない理由です。

于 2013-11-07T15:08:21.670 に答える
2

あなたの問題の解決策はこれです:

Map<String, ? extends Set<? extends Animal>> animalMap;
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();
animalMap = dogMap;

Set<Dog>ではなくSet<? extends Animal>、むしろそれを拡張するためです。

于 2013-11-07T15:59:12.023 に答える
1

その理由については、後で説明します。今のところ、これがコンパイルされることに注意してください。

Map<String, Set<? extends Animal>> animalMap;
Map<String, Set<? extends Animal>> dogMap 
    = new HashMap<String, Set<? extends Animal>>();
Set<Dog> dogMapVal = new HashSet<Dog>();
dogMap.put("fido", dogMapVal);
animalMap = dogMap; 
于 2013-11-07T15:07:59.343 に答える
0

犬は動物と等しくないので、それを拡張するだけです。

画像、どこかでこのコードを使用するコードがある場合、そこに犬を入れます。後、どこかでもう一度使いたいと思ったら、ここに犬を置いたと思ったので、犬を取り戻しました。しかし、誰かが猫やウサギを入れるとしたら?

これが理由です。

于 2013-11-07T15:10:45.187 に答える