JLS的哪一部分表示匿名类不能拥有public / protected / private成员类 [英] Which part of JLS said anonymous classes cannot have public/protected/private member classes

查看:211
本文介绍了JLS的哪一部分表示匿名类不能拥有public / protected / private成员类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑这段代码:

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 modifiers public, protected, or private (§6.6), or the modifier static (§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 modifiers protected and private (§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>修饰符?

额外注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):


  1. 匿名 Cloneable 既不是会员类也不是本地类

  2. PrivateInnerClass 是一个成员类,但不是本地类

  1. The anonymous Cloneable is neither a member class nor a local class.
  2. 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.

推荐答案

您有:


  1. 顶级类 TopLevelClass 未嵌套(因此被命名,非本地,不是匿名)

  2. 二级类,一个扩展 Clonable 的无名类,并且不是任何类的成员:是匿名的(内部类) ,不是会员,在当地范围但不是'lo cal class')

  3. 三级类 PrivateInnerClass ,匿名类的成员:是嵌套的,不是本地的,不是匿名的,是非静态的内部类

  1. Top-Level Class TopLevelClass : not nested (hence is named, not local, not anonymous)
  2. 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')
  3. 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.




  1. 在标识符之前限制修饰符

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆