在执行提取表达式重构时,我偶然发现了 Eclipse 4.4 和 Java 8 build 45 中的一些奇怪行为,至少对我而言是这样。以下示例显示了在应用提取重构之前的原始且无错误的代码:
import java.util.Map;
import java.util.Set;
public class MyMap<K, V> {
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
for (Map.Entry<? extends K, ? extends V> entry : mapToCopy.entrySet()) {
}
}
}
Eclipse 重构的结果如下所示,并导致下面的错误消息涉及对 entrySet
的读取访问权限在循环声明中:
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
Set<?> entrySet = mapToCopy.entrySet();
for (Map.Entry<? extends K, ? extends V> entry : entrySet) {
^^^^^^^^
}
}
Type mismatch: cannot convert
from element type capture#3-of ?
to Map.Entry<? extends K,? extends V>
我更改了 entrySet
的声明类型至 Set<Map.Entry<? extends K, ? extends V>>
.这一次,错误在声明的初始值设定项中指出:
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
Set<Map.Entry<? extends K, ? extends V>> entrySet = mapToCopy.entrySet();
^^^^^^^^^^^^^^^^^^^^
for (Map.Entry<? extends K, ? extends V> entry : 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>>
由于原始代码确实可以编译,所以我有点不解。也许有人可以帮助我并给出解释?提前致谢!
最佳答案
让我们先回顾一下原始出处:
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
for (Map.Entry<? extends K, ? extends V> entry : mapToCopy.entrySet()) {
}
}
在内部(和运行时),这将被编译并作为:
public void putAll(final Map mapToCopy) {
for (Iterator<Map.Entry> iterator = mapToCopy.iterator; iterator.hasNext();) {
}
}
哪里? extends K
和 ? extends V
类型删除后将替换为一些真实类型。编译器会知道这些类型是什么,不会引发 Exception
。类型不兼容。
另一方面,如果您将源代码重构为此,
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
Set<Entry<? extends K, ? extends V>> entrySet = mapToCopy.entrySet();
^^^^^^^^
for (Map.Entry<? extends K, ? extends V> entry : entrySet) {
}
}
那么编译器将没有证据表明 entrySet
持有与Map.Entry<? extends K, ? extends V>
相同的类型,只是因为通配符 ( ?
) 总是代表一些未知,即不能保证来自 entrySet
的通配符的输入键值将与 entry
相同的键值(来自循环)。由于不能百分百确定这些类型是否兼容,编译器会引发编译时错误,**即使**您可能确信这些类型在运行时是相同的。
关于java - 提取具有通用返回类型的表达式后类型不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31205972/