Mar*_*cus 5 java generics refactoring types capture
在执行提取表达式重构时,我偶然发现了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()) {
}
}
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
我改变的声明的类型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>>
Run Code Online (Sandbox Code Playgroud)
由于原始代码编译,我有点困惑.也许有人可以帮助我并给出解释?提前致谢!
我们先回顾一下原始出处:
public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
for (Map.Entry<? extends K, ? extends V> entry : mapToCopy.entrySet()) {
}
}
Run Code Online (Sandbox Code Playgroud)
在内部(和运行时),这将被编译并工作为:
public void putAll(final Map mapToCopy) {
for (Iterator<Map.Entry> iterator = mapToCopy.iterator; iterator.hasNext();) {
}
}
Run Code Online (Sandbox Code Playgroud)
其中? 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) {
}
}
Run Code Online (Sandbox Code Playgroud)
那么编译器将没有证据表明 与entrySet 具有相同的类型Map.Entry<? extends K, ? extends V>,仅仅是因为通配符 ( ?) 始终代表未知的东西,即不能保证 的entrySet条目键值中的通配符将与 的entry键相同值(来自循环)。由于不能百分百确定类型兼容,编译器会引发编译时错误,**即使**您可能确信这些类型在运行时是相同的。
| 归档时间: |
|
| 查看次数: |
132 次 |
| 最近记录: |