使用 Map.entrySet() 时类型不匹配
Type mismatch when using Map.entrySet()
我遇到以下情况:在下面的代码中,方法 foo
可以编译,而方法 bar
不会。在方法调用 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>>
有趣的是,Eclipse 的快速修复建议
Change type of 's' to Set<Entry<? extends K, ? extends V>>
它只更改了代码,因为 quickfix 忽略了它自己的建议,而是将 s
的类型更改为 Set<?>
。
我正在使用 JDK1.8.0_51 和 Eclipse 4.4.0。也许它与通配符或捕获有关?任何帮助或建议将不胜感激。提前致谢!
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();
^^^^^^^^^^^^^^
}
}
假设 K 和 V 是数字。该声明不会 link 随映射传入的类型到条目集中使用的类型。虽然我们知道它永远不会发生,但如果 map 是 Map<Integer,Integer>
那么声明允许 s 是 Set<Entry<Double,Double>>
因为它仍然扩展 Number.
因此,如果您明确表示这些类型匹配,可以这样写:
public <K0 extends K, V0 extends V> void bar(Map<K0,V0> map) {
Set<Entry<K0,V0>> s = map.entrySet();
}
您的意思很明确,'s' 的类型将与 'map' 的类型完全匹配。因此它编译愉快。
简短的回答是,如果您按照问题中的方式声明 Set,则可以向其中添加不符合传递给方法的对象类型的条目。 Java 没有保留足够的信息来检查 Set 定义中的“?extends K”是否与方法参数中的“?extends K”相同。
为避免这种情况 Java 要求您将分配声明为:
Set<? extends Map.Entry<? extends K,? extends V>> s = map.entrySet();
...您会发现您无法将自己的条目添加到此集合中 - 至少,如果不进行大量错误转换,则会产生大量警告。
正如上面提到的那样,这个问题更详细地涵盖了主题:Generic Iterator on Entry Set
我遇到以下情况:在下面的代码中,方法 foo
可以编译,而方法 bar
不会。在方法调用 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>>
有趣的是,Eclipse 的快速修复建议
Change type of 's' to Set<Entry<? extends K, ? extends V>>
它只更改了代码,因为 quickfix 忽略了它自己的建议,而是将 s
的类型更改为 Set<?>
。
我正在使用 JDK1.8.0_51 和 Eclipse 4.4.0。也许它与通配符或捕获有关?任何帮助或建议将不胜感激。提前致谢!
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();
^^^^^^^^^^^^^^
}
}
假设 K 和 V 是数字。该声明不会 link 随映射传入的类型到条目集中使用的类型。虽然我们知道它永远不会发生,但如果 map 是 Map<Integer,Integer>
那么声明允许 s 是 Set<Entry<Double,Double>>
因为它仍然扩展 Number.
因此,如果您明确表示这些类型匹配,可以这样写:
public <K0 extends K, V0 extends V> void bar(Map<K0,V0> map) {
Set<Entry<K0,V0>> s = map.entrySet();
}
您的意思很明确,'s' 的类型将与 'map' 的类型完全匹配。因此它编译愉快。
简短的回答是,如果您按照问题中的方式声明 Set,则可以向其中添加不符合传递给方法的对象类型的条目。 Java 没有保留足够的信息来检查 Set 定义中的“?extends K”是否与方法参数中的“?extends K”相同。
为避免这种情况 Java 要求您将分配声明为:
Set<? extends Map.Entry<? extends K,? extends V>> s = map.entrySet();
...您会发现您无法将自己的条目添加到此集合中 - 至少,如果不进行大量错误转换,则会产生大量警告。
正如上面提到的那样,这个问题更详细地涵盖了主题:Generic Iterator on Entry Set