考虑这段代码:
public class TopLevelClass {
Cloneable c = new Cloneable() {
private int privateField;
private void privateMethod() {};
};
}
有一个匿名类,它有一个private
成员字段和一个private
成员方法。它已成功编译。
然后考虑这个:
public class TopLevelClass {
Cloneable c = new Cloneable() {
private class PrivateInnerClass {}
};
}
有一个匿名类有一个private
成员类。然而...
- javac 说:
error: modifier private not allowed here
- Eclipse 说:
Illegal modifier for the local class PrivateInnerClass; only abstract or final is permitted
真的是本地类吗?
什么?为什么匿名类不能有public
,protected
或private
(以下简称those
)成员类,但可以有those
成员字段和方法?很困惑,我调查了 JLS。由于 Eclipse 所说的,我首先查看了本地类:
14.3. 本地类声明
本地类是一个嵌套类(第 8节),它不是任何类的成员,并且有一个名称(第 6.2 节、第6.7节)。
如果本地类声明包含任何访问修饰符public
、protected
或private
( §6.6 ) 或修饰符( §8.1.1 ),则会出现编译时错误。static
所以本地类不能有those
修饰符。但是PrivateInnerClass
是匿名的成员Cloneable
,所以它不是本地类,仍然可以有those
修饰符。
然后我查看了类修饰符:
8.1.1。类修饰符
访问修饰符
public
( §6.6 ) 仅适用于顶级类 ( §7.6 ) 和成员类 ( §8.5 ),而不适用于本地类( §14.3 ) 或匿名类 ( §15.9.5 )。
访问修饰符protected
和private
(第 6.6 节)仅适用于直接封闭类或枚举声明(第 8.5 节)中的成员类。
ButPrivateInnerClass
是一个成员类,并且它在一个直接封闭的类中,匿名Cloneable
,所以它仍然可以those
在理论上有修饰符。其他部分我也查了,还是没找到相关规定。
那么Java语言规范的哪一部分说匿名类的成员类不能有those
修饰符?
额外说明1:一些答案争论成员类和本地类,所以我做了一个测试,可以得出结论(除非修饰符很重要):
- 匿名
Cloneable
者既不是成员类也不是本地类。 - 是
PrivateInnerClass
成员类,但不是本地类。
以下是我的测试代码:
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
}
}
额外说明 2: 查看普通类的声明(JLS §8.1):
普通类声明: ClassModifiers opt class Identifier TypeParameters opt Super opt Interfaces opt ClassBody
据我了解,当Identifier
该类是 XXX 类时,§8.1.1所说的是限制修饰符 of Identifier
,而不是限制其他声明中的修饰符ClassBody
of Identifier
。否则,匿名类甚至不能有those
成员字段和方法。
任何答案,尤其是不同意额外注释 2 的答案,都必须指出为什么those
允许成员字段和方法。
附注3:如果您认为JLS没有这部分,您仍然需要提供可靠的文档来解释为什么those
禁止成员类以及为什么those
允许成员字段和方法。