【发布时间】:2015-09-21 05:54:25
【问题描述】:
在执行提取表达式重构时,我偶然发现了 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>>
由于原始代码确实可以编译,我有点困惑。也许有人可以帮助我并给出解释?提前致谢!
【问题讨论】:
-
请注意
Set<? extends Map.Entry<? extends K, ? extends V>> entrySet = mapToCopy.entrySet();会起作用。 JLS § 14.4.2 在增强的for语句中讨论了Iterable的翻译。另见this answer -
@AndyBrown:请您详细说明“请注意,[...] 会起作用”。我必须修改什么才能使其正常工作?
-
在java8中,也可以试试
map.forEach( (key,value)->{ ... } )。键/值被推断为正确的类型,作为 K/V 的某些未知子类型。如果我们指定类型,API 也足够灵活 -map.forEach( (K key, V value)->{ ... } )
标签: java generics types refactoring capture