2

誰かが説明できますか、なぜ次のコードがコンパイルされないのですか?
部分的に特殊化されたMapとMap.Entryを作成しています。

public class Trie<T> implements Map<String, T> {
    private class TrieEntry<S> implements Map.Entry<String, S> {
        // stupid implementation here
    }
    // uninterested code here
}

ここではすべて問題ありませんが、entrySet()メソッドを実装しています。

public Set<java.util.Map.Entry<String, T>> entrySet() {
    Set<java.util.Map.Entry<String, T>> x = new HashSet<TrieEntry<T>>();
    // some uninterested code here
}

Eclipseは言う

HashSet<Trie<T>.TrieEntry<T>>「タイプの不一致:からに変換できませんSet<Map.Entry<String,T>>

だから、私の心の中TrieEntry<T>で展開されるべきでMap.Entry<String, T>あり、それは定義の表現と一致しています。

私はどこが間違っていますか?

4

2 に答える 2

5

あなたは正しいTrieEntry<T>ですMap.Entry<String, T>。AHashSet<TrieEntry<T>>もですが、Set<TrieEntry<T>>ではありませんSet<Map.Entry<String, T>>

もしそうなら、あなたはこれを行うことができます:

Set<TrieEntry<T>> trieSet = ...;
Set<Map.Entry<String, T>> mapSet = trieSet;
mapSet.add(mapEntry);

したがって、trieSetにはMap.Entry<String, T>!が含まれるようになります。これはジェネリックを壊します。

では、この特定の問題をどのように解決するのでしょうか?簡単-制限付きのワイルドカードを使用します。

Set<? extends Map.Entry<String, T>> x = new HashSet<TrieEntry<T>>();

? extends Map.Entry<String, T>「少なくとも「」であるものなら何でも」と読むことができますMap.Entry<String, T>


さて、今あなたの実装の問題に。私は実際、これはメソッドentrySet()の現在の定義のため、この方法では解決できないと信じています。を返す必要? extends Map.Entry<String, T>がありますが、を返しますMap.Entry<String, T>

実際には、まさにこの問題に関するバグレポート(または機能要求)があります。提出日と優先順位を見ると、すぐに修正されることは期待できません。

したがって、2つのオプションがあります。

  1. TrieEntryクラスを削除して代わりに使用してみてくださいMap.Entry。キーや値に情報を保存してください。

  2. インターフェイスを削除Mapし、カスタムentrySetメソッドがを返すようにします? extends Map.Entry<String, T>

どちらの解決策も理想的ではないかもしれませんし、より良い解決策があるかもしれませんが、これが私が現在あなたに話すことができるすべてです。

于 2012-04-08T21:04:52.540 に答える
4

HashSetもちろん、を実装SetしますがHashSet<some subclass of X>、のサブタイプではありませんSet<X>。あなたはこれを行うことができます:

Set<? extends Map.Entry<String, T>> x = new HashSet<TrieEntry<T>>();

ただし、後でメソッドで問題が発生する可能性がありますentrySet(メソッドから返す必要があるため、メソッドから返すことはできませんSet<Map.Entry<String, T>>)。

別の解決策はこれを行うことです:

Set<Map.Entry<String, T>> x = new HashSet<Map.Entry<String, T>>();

TrieEntry<T>これにオブジェクトを追加Setし、から返すこともできますentrySet()

TrieEntrytypeパラメーターを省略し、囲んでいるクラスのtheをS使用することで、内部クラスを単純化することもできると思います。T

class Trie<T> implements Map<String, T> {
    private class TrieEntry extends Map.Entry<String, T> {
        // ...

        @Override
        public T getValue() {
            // ...
        }
    }

    // ...
}
于 2012-04-08T21:02:29.353 に答える