java - 具有上限的通配符类型变量的迭代器

标签 java generics

大家好,我尝试扩展 HashMap<String,String>执行“全小写”规则

public class HttpQueryMap extends HashMap<String,String>
{    
    ...
    @Override
    public void putAll(Map<? extends String, ? extends String> m)
    {       
        ...
        Iterator<Map.Entry<String,String>> iterator = m.entrySet().iterator();
        ...      
    }
    ... 
}

编译时出错

incompatible types
required: Iterator<Entry<String,String>>
found:    Iterator<Entry<CAP#1,CAP#2>>
where CAP#1,CAP#2 are fresh type-variables:
CAP#1 extends String from capture of ? extends String
CAP#2 extends String from capture of ? extends String

下一个解决方法可以完成这项工作,但它真的很难看:

public class HttpQueryMap extends HashMap<String,String>
{    
    ...
    @Override
    public void putAll(Map<? extends String, ? extends String> m)
    {       
        ...
        Map<String,String> m_str=new HashMap<String,String>();
        m_str.putAll(m);
        Iterator<Map.Entry<String,String>> iterator = m_str.entrySet().iterator();
        ...      
    }
    ... 
 }

据我了解,问题是类型变量 String用于 Iterator<Map.Entry<String,String>>不扩展 String (本身)用于 Map<? extends String, ? extends String> m 的声明中

最佳答案

没有迭代器

最简单的方法是使用for-each 循环。即使在这种情况下,您也需要使用与给定 map 中相同的通配符对条目进行参数化。原因是 Entry<? extends String, ? extends String>不是 Entry<String, String> 的子类型.事实Stringfinal类在这里无关紧要,因为编译器对此一无所知。

for (Entry<? extends String, ? extends String> entry : m.entrySet()) {
    String key = entry.getKey();
    String value = entry.getValue();
}

使用迭代器

如果你真的需要一个迭代器,编译的语法有点令人费解:

Iterator<? extends Entry<? extends String, ? extends String>> iterator =
    m.entrySet().iterator();

while (iterator.hasNext()) {
    Entry<? extends String, ? extends String> entry = iterator.next();
    String key = entry.getKey();
    String value = entry.getValue();
}

我原本期望迭代器只是类型 Iterator<Entry<? extends String, ? extends String>> , 乍一看似乎是 iterator() 的返回类型在 Set<Entry<? extends String, ? extends String>> 上调用的方法这又似乎是 entrySet() 的返回类型调用Map<? extends String, ? extends String> .

然而,它比这复杂一点。我在这里找到了一个可能的答案:

http://mail-archives.apache.org/mod_mbox/harmony-dev/200605.mbox/%3Cbb4674270605110156r4727e563of9ce24cdcb41a0c8@mail.gmail.com%3E

有趣的部分是:

The problem is that the entrySet() method is returning a Set<Map.Entry<capture-of ? extends K, capture-of ? extends V>>, which is incompatible with the type Set<Map.Entry<? extends K, ? extends V>>. It's easier to describe why if I drop the extends K and extends V part. So we have Set<Map.Entry<?, ?> and Set<Map.Entry<capture-of ?, capture-of ?>>.

The first one, Set<Map.Entry<?, ?>> is a set of Map.Entries of different types - ie it is a heterogeneous collection. It could contain a Map.Entry<Long, Date> and a Map.Entry<String, ResultSet>> and any other pair of types, all in the same set.

On the other hand, Set<Map.Entry<capture-of ?, capture-of ?>> is a homogenous collection of the same (albeit unknown) pair of types. Eg it might be a Set<Map.Entry<Long, Date>>, so all of the entries in the set MUST be Map.Entry<Long, Date>.

关于java - 具有上限的通配符类型变量的迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16753587/

相关文章:

java - C3P0 配置!在哪里以及如何?

java - 如何在处理中查找缩放形状上的距离/检测鼠标悬停

Java Generics Hell - 传入这个但它想要类型 T

java - liferay 的 service.xml 中的 Blob 数据类型

java - 如何创建一个以唯一整数作为元素的数组

java - 如何使用 JPA 从单列映射到多个表

list - 关于映射和泛型的混淆

java - 接口(interface)、继承和子类型

swift - 如何在 Swift 中创建 Hashable 集合

.net - 显式类型成员约束中的 "or"