4

このコードの何が問題なのか疑問に思っています:

Map <? extends String, ? extends Integer> m = null;
Set<Map.Entry<? extends String, ? extends Integer>> s = m.entrySet();

コンパイラは次のエラー メッセージを表示します。

Set<Map.Entry<capture#1-of ? extends String,capture#2-of ? extends Integer>>型の不一致: からに変換できませんSet<Map.Entry<? extends String,? extends Integer>>

の種類は何sですか?Eclipse は示唆してSet<?>いますが、私はそれよりも具体的にしようとしています。

4

1 に答える 1

9

この問題は、次の古い Apache スレッドで対処されています。

問題は、メソッドが型と互換性のない をentrySet()返している ことです。and の部分を削除すると、その理由を簡単に説明できます。したがって、 と があります。Set<Map.Entry<capture-of ? extends K, capture-of ? extends V>>Set<Map.Entry<? extends K, ? extends V>>extends Kextends VSet<Map.Entry<?, ?>Set<Map.Entry<capture-of ?, capture-of ?>>

最初のものSet<Map.Entry<?, ?>>は、さまざまなタイプの Map.Entries のセットです。つまり、異種のコレクションです。Map.Entry<Long, Date>aと aMap.Entry<String, ResultSet>>およびその他のタイプのペアをすべて同じセットに含めることができます 。

一方、Set<Map.Entry<capture-of ?, capture-of ?>>は同じ (ただし不明な) 型のペアの同種のコレクションです。たとえば、 である可能性がある Set<Map.Entry<Long, Date>>ため、セット内のすべてのエントリは である必要があります Map.Entry<Long, Date>

問題の核心は、最上位のワイルドカードが をキャプチャすることです。つまり、それらは本質的に 1 回限りの型パラメーターです。対照的に、ネストされたワイルドカードはキャプチャされず、多少異なる意味を持ちます。

したがって、単純化のために境界を取り除き、次のように宣言します。

Map<?, ?> m;

「特定の未知のタイプのキーと特定の未知のタイプの値のマップ」を意味します。

しかし、宣言する

Set<Map.Entry<?, ?>> s;

「任意のタイプのキーと値のエントリのセット」を意味します。

式がそれを返すのではなく、「特定の未知のタイプのキーと特定のm.entrySet()未知のタイプの値のエントリのセット」を返したくないため、ここで問題が発生します。ジェネリックは共変ではないため、これらの型は互換性がありません: Aは a ではありません。Set<Type>Set<SuperType>

(ネストされたワイルドカードのニュアンスを理解するのに役立つこの魅力的な投稿を参照してください。ジェネリック メソッドの複数のワイルドカードにより、Java コンパイラ (および私!) は非常に混乱します。)

1 つの回避策は、正式な型パラメーターを入れ子にすることができるという事実を利用するキャプチャ ヘルパーメソッドを使用することです。

private <K extends String, V extends Integer> void help(final Map<K, V> map) {
    final Set<Map.Entry<K, V>> entries = map.entrySet();
    // logic
}

...

Map<? extends String, ? extends Integer> m = null;
help(m);

StringIntegerは bothであるため、これは不自然な例ですfinalが、概念を示しています。

より簡単な回避策は次のとおりです。

Set<? extends Map.Entry<? extends String, ? extends Integer>> s = m.entrySet();

これは、非null要素を に追加することsは許可されていないことを意味しますが、Set返された byの場合entrySetaddおよびメソッドはとにかくサポートされていません (この点addAllを明確にしてくれたことに newacct に感謝します)。

于 2013-09-20T01:09:48.053 に答える