java中的泛型专业化

时间:2012-04-08 20:35:43

标签: java generics

有人可以解释,为什么下一个代码没有编译? 我正在为它创建一个部分专用的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>,并且它符合定义中的表达。

我哪里错了?

2 个答案:

答案 0 :(得分:5)

TrieEntry<T>Map.Entry<String, T>,你是对的。 HashSet<TrieEntry<T>>也是Set<TrieEntry<T>>,但 <{1}}。

如果是,你可以这样做:

Set<Map.Entry<String, T>>

所以现在trieSet现在包含Set<TrieEntry<T>> trieSet = ...; Set<Map.Entry<String, T>> mapSet = trieSet; mapSet.add(mapEntry); !这会打破泛型。

那么如何解决这个特殊问题呢?轻松 - 使用有界通配符:

Map.Entry<String, T>

您可以将Set<? extends Map.Entry<String, T>> x = new HashSet<TrieEntry<T>>(); 视为“至少? extends Map.Entry<String, T>”的任何内容。


好的,现在来看你的实施问题。我实际上相信,由于方法entrySet()的当前定义,这是无法解决返回Map.Entry<String, T>,但 返回? extends Map.Entry<String, T>

对于这个问题,实际上有一个bug report(或功能请求)。查看提交日期和优先级,很快就无法实现修复。

所以你有两个选择:

  1. 放弃Map.Entry<String, T>课程并尝试使用TrieEntry代替,将信息存储在您的密钥和/或值中。

  2. 放弃Map.Entry界面,让自定义Map方法返回entrySet

  3. 这两种解决方案可能都不理想,而且可能有更好的解决方案,但这就是我目前可以告诉你的所有内容。

答案 1 :(得分: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()返回。

我认为您还可以通过省略类型参数TrieEntry来简化S内部类,并使用封闭类中的T

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

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

    // ...
}