具有上限的通配符类型变量的迭代器 [英] Iterator of a wildcard type variable with upper bound

查看:126
本文介绍了具有上限的通配符类型变量的迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,我尝试扩展一个 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();
...
}
...
}

我得到一个编译时错误

 不兼容类型
required:Iterator< Entry< String,String> >找到
:Iterator< Entry< CAP#1,CAP#2>>
其中CAP#1,CAP#2是新鲜的类型变量:
CAP#1从捕获?扩展字符串
CAP#2扩展字符串捕获?扩展字符串

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

  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();
...
}
...
}

据我所知,问题在于 Iterator< Map.Entry< String,String>>中使用的类型变量 String 不会扩展 Map< ;?声明中使用的 String (本身)。扩展字符串,? extends String>没有Iterator

最简单的方法是使用 for-each循环。即使在这种情况下,您也需要使用与给定映射中相同的通配符对Entry进行参数化。原因是 Entry <?扩展字符串,? extends String> 不是条目< String,String> 的子类型。 String 是一个 final 类的事实在这里并不重要,因为编译器不知道这一点。

String key = entry(>>

  .getKey(); 
String value = entry.getValue();

$ / code>



使用Iterator



如果你确实需要一个Iterator,那么编译的语法有点令人费解:

  Iterator <?扩展Entry<扩展字符串,? extends String>> iterator = 
m.entrySet()。iterator();

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

我原本以为迭代器只能是迭代<条目< ;?扩展字符串,?扩展字符串>> ,它最初看起来是 Set< code> iterator()方法的返回类型。 ;条目< ;?扩展字符串,?扩展字符串>> ,它依次类似于在 Map< ;?上调用的 entrySet()的返回类型。扩展字符串,? extends String>



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

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



有趣的部分是这样的:


问题是 entrySet()方法返回一个
Set< Map.Entry< capture-of?扩展K,捕获?扩展V>>
,这与 Set< Map.Entry <?类型不兼容。延伸K,?扩展V>>
如果我放弃扩展K 扩展V 部分,为什么要更容易描述。
因此,我们有 Set< Map.Entry<?,?> Set< Map.Entry Set< Map.Entry<?,?>>< / code& ;> 是一组不同
类型的Map.Entries集合,即它是一个异构集合。它可以包含
Map.Entry< Long,Date> 和一个 Map.Entry< String,ResultSet>>

另一方面, Set< Map 和任何其他
类型的对,都在同一个集合中。 .Entry >>
是相同(尽管未知)类型的同类
集合。例如它可能是
Set< Map.Entry< Long,Date>> ,所以集合中的所有条目必须是
Map.Entry< Long,Date>



Hello everybody I try to extend a HashMap<String,String> to enforce a "all-lowercase" rule

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();
        ...      
    }
    ... 
}

I get a compile-time error

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

The next work-around does the job but it is really ugly:

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();
        ...      
    }
    ... 
 }

As far as I understand the problem is that the type variable String used in the Iterator<Map.Entry<String,String>> does not extend String (itself) used in the declaration of Map<? extends String, ? extends String> m

解决方案

Without Iterator

The easiest way is to use a for-each loop. Even in this case, you need the parametrize the Entry with the same wildcards as in the given map. The reason is that Entry<? extends String, ? extends String> is not a subtype of Entry<String, String>. The fact that String is a final class is irrelevant here, because the compiler has no knowledge of that.

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

With Iterator

If you really need an Iterator, the syntax that does compile is a bit baffling:

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();
}

I originally expected the iterator to be only of type Iterator<Entry<? extends String, ? extends String>>, which at first appears to be the return type of iterator() method called on a Set<Entry<? extends String, ? extends String>> which in turns appears to be the return type of entrySet() called on Map<? extends String, ? extends String>.

However, it is a bit more complex than that. I've found a probable answer in here:

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

The interesting part is this:

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>.

这篇关于具有上限的通配符类型变量的迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆