Consider this piece of code:
public class TopLevelClass {
Cloneable c = new Cloneable() {
private int privateField;
private void privateMethod() {};
};
}
There is an anonymous class that has a private
member field and a private
member method. It has been successfully compiled.
Then consider this one:
public class TopLevelClass {
Cloneable c = new Cloneable() {
private class PrivateInnerClass {}
};
}
There is an anonymous class that has a private
member class. However...
- javac said:
error: modifier private not allowed here
- Eclipse said:
Illegal modifier for the local class PrivateInnerClass; only abstract or final is permitted
Really local class?
What? Why anonymous classes cannot have public
, protected
or private
(hereinafter referred to as those
) member classes while they can have those
member fields and methods? Confused, I looked into JLS. Because of what Eclipse stated, I looked into local classes first:
14.3. Local Class Declarations
A local class is a nested class (§8) that is not a member of any class and that has a name (§6.2, §6.7).
It is a compile-time error if a local class declaration contains any of the access modifierspublic
,protected
, orprivate
(§6.6), or the modifierstatic
(§8.1.1).
So local class cannot have those
modifiers. But PrivateInnerClass
is a member of the anonymous Cloneable
, so it is not a local class and is still able to have those
modifiers.
Then I looked into class modifiers:
8.1.1. Class Modifiers
The access modifier
public
(§6.6) pertains only to top level classes (§7.6) and to member classes (§8.5), not to local classes (§14.3) or anonymous classes (§15.9.5).
The access modifiersprotected
andprivate
(§6.6) pertain only to member classes within a directly enclosing class or enum declaration (§8.5).
But PrivateInnerClass
is a member class, and it's within a directly enclosing class, the anonymous Cloneable
, so it can still have those
modifiers on theory. I looked into other parts as well, but I still couldn't find relevant provisions.
So which part of Java Language Specification said a member class of an anonymous class cannot have those
modifier?
Extra Note 1: Some answer argued about member classes and local classes, so I made a test that can conclude that (unless modifiers matters):
- The anonymous
Cloneable
is neither a member class nor a local class. - The
PrivateInnerClass
is a member class, but not a local class.
The following is my test code:
public class TopLevelClass {
Cloneable c = new Cloneable() {
class PrivateInnerClass {}
};
public static void main(String[] args) throws ClassNotFoundException {
Class<?> c1 = Class.forName("TopLevelClass$1");
Class<?> c2 = Class.forName("TopLevelClass$1$PrivateInnerClass");
System.out.println(c1.isMemberClass()); // false
System.out.println(c1.isLocalClass()); // false
System.out.println(c2.isMemberClass()); // true
System.out.println(c2.isLocalClass()); // false
}
}
Extra Note 2: Review the declaration of a normal class (JLS §8.1):
NormalClassDeclaration: ClassModifiersopt class Identifier TypeParametersopt Superopt Interfacesopt ClassBody
In my understanding, when the Identifier
class is an XXX class, what §8.1.1 stated is restricting the modifier of Identifier
, not the modifiers in other declarations in ClassBody
of Identifier
. Otherwise, anonymous classes even cannot have those
member fields and methods.
Any answer, especially which disagree with Extra Note 2, must point out why those
member fields and methods are allowed.
Extra Note 3: If you think there isn't such part of JLS, you'll still need to give a reliable document to explain why those
member classes are forbidden and why those
member fields and methods are allowed.