不兼容的通用通配符捕获

时间:2010-12-16 10:15:38

标签: java generics wildcard capture

在以下代码段中:

package test;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

public class WildcardsTest<K, V> {
    private Iterator<Map.Entry<K, ? extends Collection<V>>> iterator;
    public WildcardsTest(Map<K, ? extends Collection<V>> map) {
        iterator = map.entrySet().iterator();
        /* Type mismatch: cannot convert from
           Iterator<Map.Entry<K,capture#1-of ? extends Collection<V>>> to
           Iterator<Map.Entry<K,? extends Collection<V>>> */
    }
}

分配不正确,尽管类型似乎完全匹配。

我已经设计了一个肮脏的解决方法,将Collection的类型指定为另一个泛型参数,如下所示:

public class WildcardsTest<K, V, C extends Collection<V>> {
    private Iterator<Map.Entry<K, C>> iterator;
    public WildcardsTest(Map<K, C> map) {
        iterator = map.entrySet().iterator();
    }
}

C参数实际上是一种“不关心”类型,只会使API复杂化,有没有办法在保持类型安全的同时摆脱它?

感谢。

2 个答案:

答案 0 :(得分:4)

这样做会起作用:

private final Iterator<? extends
    Map.Entry<K, ? extends Collection<V>>
> iterator;

你仍然可以像这样使用迭代器:

public void foo(){
    while(iterator.hasNext()){
        Entry<K, ? extends Collection<V>> entry = iterator.next();
        Collection<V> value = entry.getValue();
    }
}

如需参考,请阅读the get and put principle(最初来自Java Generics and Collections

答案 1 :(得分:2)

  

分配不正确,但类型似乎完全匹配。

两个? - 通配符可以绑定到两个不同的类。换句话说,很明显存在类型不匹配的问题:

private Iterator<Map.Entry<K, ArrayList<V>>> iterator;
public WildcardsTest(Map<K, HashSet<V>> map) {
    iterator = map.entrySet().iterator();
}

当你引入C时,你“强迫它们”引用同一个类。