JLS的哪一部分表示匿名类不能拥有public / protected / private成员类 [英] Which part of JLS said anonymous classes cannot have public/protected/private member classes
问题描述
考虑这段代码:
public class TopLevelClass {
Cloneable c = new Cloneable() {
private int privateField;
private void privateMethod() {};
};
}
有一个匿名类,其中包含 private
成员字段和私有
成员方法。它已成功编译。
There is an anonymous class that has a private
member field and a private
member method. It has been successfully compiled.
然后考虑这一个:
public class TopLevelClass {
Cloneable c = new Cloneable() {
private class PrivateInnerClass {}
};
}
有一个匿名类,其中包含 private
成员类。但是......
There is an anonymous class that has a private
member class. However...
- javac说:
错误:此处不允许使用修饰符
- Eclipse说:
本地类PrivateInnerClass的非法修饰符;只允许抽象或最终
真正的本地课程?
- 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?
什么? 为什么匿名类不能 public
, protected
或 private
(以下简称那些
)成员类,但他们可以拥有那些
成员字段和方法?困惑,我查看了JLS。由于Eclipse的说法,我查看了本地课程首先:
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。本地类声明
本地类是一个嵌套类(§8)不是任何类的成员且具有名称(§6.2,§6.7。
它是如果本地类声明包含任何访问修饰符public
,protected
或<$ c,则为编译时错误$ c> private (§6.6)或修饰语static
(§8.1.1。
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).
因此本地类不能有那些
修饰符。但 PrivateInnerClass
是匿名 Cloneable
的成员,因此它不是本地类并且仍然能够那些
修饰符。
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.
然后我查看类修饰符:
8.1.1。类修饰符
访问修饰符
public
(§6.6)仅适用于顶级课程(§7.6)和成员类(§8.5),而不是本地课程(§14.3)或匿名类(< a href =http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9.5\"rel =noreferrer>§15.9.5 )。$
访问修饰符protected
和private
(§6.6)仅适用于直接封闭类中的成员类或枚举声明(§8.5)。
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
,因此它理论上仍然可以有那些
修饰符。我也查看了其他部分,但我仍然找不到相关条款。
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.
那么Java语言规范的哪一部分说成员类一个匿名类不能那些$ c> c>修饰符?
额外注1:有些回答是关于成员类和本地类的,所以我做了一个测试,可以得出结论(除非修饰符很重要):
Extra Note 1: Some answer argued about member classes and local classes, so I made a test that can conclude that (unless modifiers matters):
- 匿名
Cloneable
既不是会员类也不是本地类。 -
PrivateInnerClass
是一个成员类,但不是本地类。
- The anonymous
Cloneable
is neither a member class nor a local class. - The
PrivateInnerClass
is a member class, but not a local class.
以下是我的测试代码:
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
根据我的理解,当标识符
类是XXX类时,§8.1.1说明是限制性的标识符
的修饰符,而不是
标识符$>
ClassBody
中其他声明的修饰符C $ C>。否则,匿名类甚至不能拥有那些
成员字段和方法。
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.
任何答案,尤其是不同意使用Extra Note 2,必须指出为什么允许那些
成员字段和方法。
Any answer, especially which disagree with Extra Note 2, must point out why those
member fields and methods are allowed.
额外注3:如果您认为JLS没有这部分,您仍然需要提供可靠的文档来解释原因这些
成员类是被禁止的,为什么允许这些
成员字段和方法。
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.
推荐答案
您有:
- 顶级类
TopLevelClass
:未嵌套(因此被命名,非本地,不是匿名) - 二级类,一个扩展
Clonable
的无名类,并且不是任何类的成员:是匿名的(内部类) ,不是会员,在当地范围但不是'lo cal class') - 三级类
PrivateInnerClass
,匿名类的成员:是嵌套的,不是本地的,不是匿名的,是非静态的内部类
- Top-Level Class
TopLevelClass
: not nested (hence is named, not local, not anonymous) - Second-Level Class, a no-name class that extends
Clonable
and is a not a member of any class: is anonymous (an inner class, is not a member, is in local scope but is not a 'local class') - Third-Level Class
PrivateInnerClass
, a member of the anonymous class: is nested, is not local, is not anonymous, is a non-static inner class
您在(2)中使用修饰符 private
。你收录的JLS文字说明这是非法的:
You are using the modifier private
in (2). Your included JLS text spells out this is illegal:
8.1.1
访问修饰符public(第6.6节)仅适用于顶级类(第7.6节)和成员类(第8.5节),不适用于本地类(第14.3节)或匿名类强>(§15.9.5)。
受保护的访问修饰符和私有(第6.6节)仅在直接封闭的类或枚举声明(第8.5节)中将仅限于成员类。
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 modifiers protected and private (§6.6) pertain only to member classes within a directly enclosing class or enum declaration (§8.5).
即。你可以在匿名类的内部(在范围内)不使用这些修饰符。
i.e. you can use none of these modifiers inside (in the scope of) an anonymous class.
回答额外注释2:
根据我的理解,当Identifier类是XXX类时,所述的§8.1.1限制了标识符的修饰符,而不是标识符的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.
-
在标识符之前限制修饰符
Restriction of modifier before Identifier
- 这在8.1.1中有详细说明。它显然适用。
- 所有修饰符都可以在成员类的标识符之前应用
-
public
可以在顶级类之前应用标识符 - 在本地/匿名类的标识符(在本地范围内声明的类)之前不能应用修饰符
- This is spelled out in 8.1.1. It clearly applies.
- All modifiers can be applied before Identifier of a member class
public
can be applied before top-level class Identifier- No modifiers can be applied before Identifier of local/anonymous classes (classes declared in local scope)
为什么会这样?
因为成员类可以被其他类直接引用(通过顶级类的成员链,但本地/匿名类永远不能在外部引用。本地/匿名类声明隐藏在本身不能被java程序的任何其他部分访问的作用域中。
Because member classes can be referenced directly by other classes (through a 'member chain' from the top-level class), but local/anonymous classes can never be referenced externally. Local/Anonymous class declarations are hidden in a scope that is itself not accessible to any other part of the java program.
修饰符仅 当声明>
ClassBody中修饰符的限制
Restriction of modifier within ClassBody
如果java程序的其他部分无法访问类标识符/声明,当然也无法访问ClassBody。
If a class Identifier/Declaration is not accessible to other parts of the java program, of course, the ClassBody is not accessible either.
因此,只要修饰符在标识符之前是非法的,修饰符就可能在ClassBody中没有可能的语义含义。
Hence, whenever a modifier is illegal before the Identifier, a modifier could have no possible semantic meaning within the ClassBody.
规则对于ClassBody中是否允许使用修饰符必须始终与之前是否允许修饰符的规则相同。
The rules for whether a modifier is allowed within ClassBody must always be identical to the rules for whether a modifier is allowed before Identifier.
所以8.1.1。限制两个地方的修饰符
So 8.1.1. restricts modifiers in both places
:)
这篇关于JLS的哪一部分表示匿名类不能拥有public / protected / private成员类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!