简体   繁体   English

使用Map.entrySet()时类型不匹配

[英]Type mismatch when using Map.entrySet()

I have the following situation: In the code below, the method foo compiles while the method bar won't. 我有以下情况:在下面的代码中,方法foo编译而方法bar不会。 At the method call entrySet (indicated in the code) the compiler says: 在方法调用entrySet (在代码中指示),编译器说:

Type mismatch: cannot convert 
from Set<Map.Entry<capture#1-of ? extends K,capture#2-of ? extends V>> 
to Set<Map.Entry<? extends K,? extends V>>

Interestingly, the quickfix of Eclipse proposes to 有趣的是,Eclipse的quickfix建议

Change type of 's' to Set<Entry<? extends K, ? extends V>>

which only changes the code because the quickfix is ignoring its own proposal and changing the type of s to Set<?> instead. 只更改代码,因为quickfix忽略了自己的提议并将s的类型改为Set<?>

I am using JDK1.8.0_51 and Eclipse 4.4.0. 我使用的是JDK1.8.0_51和Eclipse 4.4.0。 Maybe it has something to do with the wildcards or captures? 也许它与通配符或捕获有关? Any help or advice would be appreciated. 任何帮助或建议将不胜感激。 Thanks in advance! 提前致谢!

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MyClass<K, V> {
    public void foo(Set<Entry<? extends K, ? extends V>> set) {
        Iterator<Entry<? extends K, ? extends V>> i = set.iterator();
    }

    public void bar(Map<? extends K, ? extends V> map) {
        Set<Entry<? extends K, ? extends V>> s = map.entrySet();
                                                 ^^^^^^^^^^^^^^
    }
}

Imagine K and V are Number. 想象一下K和V是数字。 The declaration does not link the types passed in with the map to those used in the entry set. 声明不会将传递给地图的类型链接到条目集中使用的类型。 Although we know it could never happen, if map is a Map<Integer,Integer> then the declaration allows s to be a Set<Entry<Double,Double>> as that still extends Number. 虽然我们知道它永远不会发生,但如果map是Map<Integer,Integer>那么声明允许s为Set<Entry<Double,Double>>因为它仍然扩展了Number。

Therefore, if you are explicit that these types match, by writing this: 因此,如果您明确表示这些类型匹配,请写下:

public <K0 extends K, V0 extends V> void bar(Map<K0,V0> map) {
    Set<Entry<K0,V0>> s = map.entrySet();
}

Your meaning is explicit, that the type of 's' will match exactly the types for 'map'. 你的意思是明确的,'s'的类型将与'map'的类型完全匹配。 Hence it compiles happily. 因此它快乐地编译。

The short answer is that, if you declared the Set in the way you have in your question, it would be possible to add entries to it which did not conform to the types of the objects passed in to the method. 简短的回答是,如果您按照问题中的方式声明了Set,则可以向其添加不符合传递给方法的对象类型的条目。 Java does not retain sufficient information to check that the "? extends K" in the Set definition is the same as the "? extends K" in the method parameter. Java没有保留足够的信息来检查Set定义中的“?extends K”是否与方法参数中的“?extends K”相同。

To avoid this Java requires you to declare the assignment as: 为了避免这种情况,Java要求您将赋值声明为:

Set<? extends Map.Entry<? extends K,? extends V>> s = map.entrySet();

... and you will find you cannot add your own entries into this set - at least, not without doing a lot of bad casting which will generate a lot of warnings. ......你会发现你不能在这个集合中添加你自己的条目 - 至少,不是没有做很多糟糕的演员会产生很多警告。

As someone mentioned above, this question covers the subject in more detail: Generic Iterator on Entry Set 正如上面提到的那样,这个问题更详细地讨论了这个主题: 入口集上的通用迭代器

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM