The following class has an inner class called Entry
. This code will not compile in Java 8 as the compiler assumes the Entry
referenced within the double curly brace initializer is of type Map.Entry
and not Scope.Entry
. This code compiles in previous versions (at least 6 and 7) of the JDK but is broken in JDK 8. My question is "why?" Map.Entry
is not imported in this class, so there is no reason for the compiler to assume that the value is of type Map.Entry
. Is there some implicit scope being brought in or something for anonymous classes?
Error:
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);
Example Code:
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);
}
}};
}
}
It's definitely not a bug, it's a side-effect of using double-brace initialization.
This type of initialization is basically a clever way to abuse instance initialization blocks. It creates an anonymous subclass of HashMap with an initialization block, and then copies that block into the beginning of its default constructor before calling it. This subclass gives priority to the Entry in the scope of its parent, rather than the scope that it's nested in. This is explained by shadowing.
From 8.1.6. Class Body and Member Declarations
Here,
C
is the anonymous inner class declared. Since it inherits fromHashMap
,java.util.Map.Entry
shadowsscope.Scope.Entry
.As for why it compiled as you wanted it to with previous versions, I have no idea. This behavior was present in those versions (the docs I referenced are from
7
), so it shouldn't have worked. So maybe those versions are bugged.