3

この質問に続いて、解決策を提供しますが、説明していません(残念ながら、回答のリンクは現在死んでいます):

次の方法を取ります。

void method(Map<?, ?> myMap) {
    Set<Map.Entry<?, ?>> set = myMap.entrySet();
    ...
}

簡単ですよね?ただし、これは jdk1.7.0_25 でのコンパイルに失敗します。

incompatible types
required: java.util.Set<java.util.Map.Entry<?,?>>
found:    java.util.Set<java.util.Map.Entry<capture#1 of ?,capture#2 of ?>>

なんてこと?Map.entrySet()は type のオブジェクトを返すように指定されているSet<Map.Entry<K, V>>ため、上記の例では をmyMap.entrySet()返しますSet<Map.Entry<?, ?>>。しかし、それはコンパイルされません!

さらに奇妙なことに、上部のリンクされた質問から、メソッドをこれに変更するとコンパイルされます。

void method(Map<?, ?> myMap) {
    Set<? extends Map.Entry<?, ?>> set = myMap.entrySet();
    ...
}

なんだ???aを呼び出すentrySetと aMap<?, ?>が返さSet<Map.Entry<K, V>>。これは、 type の変数には代入できませんがSet<Map.Entry<K, V>>、タイプSet<? extends Map.Entry<K, V>>?????

ここで何が起こっているのかを明らかにできる人はいますか? これは、少なくとも 2 レベルの深さのワイルドカード型を使用してメソッドを記述するときはいつでも、? extends ...どこかに作成することを覚えておく必要があるということですか?

4

1 に答える 1

6

それらのそれぞれ?は独立して変化する可能性があるため<?,?>、 の宣言内の が の宣言内の とmyMap一致するという保証はありません。<?,?>set

これが意味することは、 を取得すると、 はすべてのタイプのスーパータイプであるため、任意のタイプのをそのセットにSet<Map<?,?>>入れることができるということです。しかし、これは (たとえば) が持つプロパティではありません。これに入れることができるマップの種類に関しては、はるかに制限されています。Soは のスーパータイプではありません。しかし、内容によっては、簡単に になる可能性があります。したがって、コンパイラはそれを type の変数に代入することを禁止する必要があり、それが起こっています。MapMap<?,?>MapSet<Map<String,Integer>>Set<Map<?,?>>Set<Map<String,Integer>>myMap.entrySet()Set<Map<String,Integer>>myMapSet<Map<?,?>>

一方、Set<? extends Map<?,?>> のサブタイプであるSet<Map<String,Integer>>ため、 のスーパータイプです。したがって、 type の変数に割り当てても問題ありません。Map<String,Integer>Map<?,?>myMap.entrySet()Set<? extends Map<?,?>>

Stringand Integerhereについて特別なことは何もありませんが、何かmyMapのマップでなければならないことに注意してください!

あなたは書くことができます

<K, V> void method(Map<K, V> myMap) {
    Set<Map.Entry<K, V>> set = myMap.entrySet();
    ...
于 2013-11-01T13:13:08.597 に答える