下面的类有一个名为Entry
的内部类。这段代码不能在Java8中编译,因为编译器假设双花括号初始化器中引用的Entry
是Map.Entry
类型,而不是Scope.Entry
类型。这段代码可以在JDK的早期版本(至少是6和7)中编译,但是在JDK8中被破坏了。我的问题是“为什么?”这个类中没有导入Map.Entry
,因此编译器没有理由假设该值是Map.Entry
类型。是否为匿名类引入了隐式作用域或其他内容?
错误:
scope/Scope.java:23: error: incompatible types: scope.Scope.Entry cannot be converted to java.util.Map.Entry for (final Entry entry : entries) {
scope/Scope.java:22: error: cannot find symbol put(entry.getName(), entry);
示例代码:
package scope;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class Scope {
public static class Entry<T> {
public String getName() {
return "Scope";
}
}
public static void main(String[] args) {
final Set<Entry> entries = new HashSet<>();
new HashMap<String, Entry>() {{
// Why does the Java 8 compiler assume this is a Map.Entry
// as it is not imported?
for (final Entry entry : entries) {
put(entry.getName(), entry);
}
}};
}
}
发布于 2014-11-14 02:53:12
这绝对不是一个bug,它是使用双花括号初始化的副作用。
new HashMap<String, Entry>() {{
for (final Entry entry : entries) {
put(entry.getName(), entry);
}
}};
这种类型的初始化基本上是滥用instance initialization blocks的一种聪明方式。它使用初始化块创建HashMap的匿名子类,然后在调用默认构造函数之前将该块复制到其默认构造函数的开头。这个子类优先于其父范围内的条目,而不是其嵌套在其中的范围。shadowing对此进行了解释。
来自8.1.6. Class Body and Member Declarations
如果C本身是一个嵌套类,则在封闭的作用域中可能存在相同类型(变量、方法或类型)和名称为m的定义。(作用域可以是块、类或包。)在所有这些情况下,成员m在中声明或由C阴影继承(§6.4.1)相同种类和名称的其他定义。强调我的
这里,C
是声明的匿名内部类。因为它继承自HashMap
,所以java.util.Map.Entry
隐藏了scope.Scope.Entry
。
至于为什么它在以前的版本中像你想要的那样编译,我不知道。这种行为在这些版本中就存在(我引用的文档来自7
),所以它不应该工作。因此,也许这些版本是错误的。
https://stackoverflow.com/questions/26913341
复制相似问题