java JLS的哪一部分说匿名类不能有公共/受保护/私有成员类
考虑这段代码:
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所述,我首先研究了local classes:
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).
所以本地类不能有those
修饰符。但是PrivateInnerClass
是匿名Cloneable
的成员,因此它不是本地类,并且仍然可以有those
修饰符
然后我研究了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).
但是PrivateInnerClass
是一个成员类,它在一个直接封闭的类中,即匿名的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)的声明:
NormalClassDeclaration: ClassModifiersopt class Identifier TypeParametersopt Superopt Interfacesopt ClassBody
在我的理解中,当Identifier
类是XXX类时,§8.1.1所述的是限制Identifier
的修饰符,而不是ClassBody
中其他声明中的修饰符。否则,匿名类甚至不能有those
成员字段和方法
任何答案,尤其是与额外注释2不一致的答案,必须指出为什么允许使用those
成员字段和方法强>
额外注意3:如果您认为JLS中没有这样的部分,您仍然需要提供一个可靠的文档来解释为什么禁止those
成员类以及为什么允许those
成员字段和方法强>
# 1 楼答案
我的最终答案包括两个论点:
JLS中没有对匿名类成员修饰符的严格限制声明。也就是说,JLS中没有这样的部分
但是根据JVM规范,匿名类不是类的成员:
JVM 7规范:声明:
所以,根据
8.5成员类型声明
匿名类不是成员类
因此,根据8.1.1。类修饰符:
这些类不是成员类,所以它们不可能提到修饰符
# 2 楼答案
你有:
TopLevelClass
:未嵌套(因此命名,非本地,非匿名)Clonable
的无名类,不是任何类的成员:是匿名的(内部类,不是成员,在局部范围内,但不是“局部类”)PrivateInnerClass
,匿名类的成员:是嵌套的,不是本地的,不是匿名的,是非静态的内部类您正在使用(2)中的修饰符
private
。您随附的JLS文本说明这是非法的:8.1.1
也就是说,你不能在匿名类中使用这些修饰符
对补充说明2的答复:
标识符前修饰语的限制
public
可以在顶级类标识符之前应用这是为什么
因为成员类可以被其他类直接引用(通过顶级类的“成员链”),但是本地/匿名类永远不能被外部引用。本地/匿名类声明隐藏在java程序的任何其他部分都无法访问的范围内
修饰符在类声明之前是合法的,而其他类可以访问该声明
类体内修饰语的限制
当然,如果java程序的其他部分无法访问类标识符/声明,那么类主体也无法访问
因此,每当一个修饰语在标识符之前是非法的,修饰语在类主体中就可能没有可能的语义
类体中是否允许修饰符的规则必须始终与标识符之前是否允许修饰符的规则相同
所以8.1.1。限制两个位置的修饰符
:)
# 3 楼答案
你错过了“包含”这个词。PrivateInnerClass是匿名类的成员,它包含在匿名类中,因此根据规则14.3,它本身不能有访问修饰符
它可以为自己的成员设置访问修饰符,但你还没有研究过
Eclipse错误消息错误地将其描述为本地
你还忽略了一点,即“private”即使是合法的,也不会添加任何内容,因为内部类无论如何都是不可见的