Подтвердить что ты не робот

Какая часть JLS говорит, что анонимные классы не могут иметь классы public/protected/private member

Рассмотрим этот фрагмент кода:

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) или модификатор static (§8.1.1).

Таким образом, у локального класса не могут быть модификаторы those. Но PrivateInnerClass является членом анонимного Cloneable, поэтому он не является локальным классом и по-прежнему может иметь модификаторы those.

Затем я просмотрел модификаторы классов:

8.1.1. Модификаторы классов

Модификатор доступа public (§6.6) относится только к классам верхнего уровня (§7.6) и классам-членам (§8.5), а не локальным классам (§14.3) или анонимные классы (§15.9.5).
Модификаторы доступа protected и private (§6.6) относятся только к классам-членам в объявлении класса или enum (§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 of Identifier. В противном случае анонимные классы даже не могут иметь those поля и методы участника.

Любой ответ, особенно, который не согласен с Extra Note 2, должен указывать, почему those поля и методы участника разрешены.


Дополнительная заметка 3: Если вы считаете, что в JLS нет такой части, , вам все равно нужно предоставить надежный документ, чтобы объяснить, почему классы those запрещены и почему those поля и методы членов разрешены.


4b9b3361

Ответ 1

У вас есть:

  • Класс верхнего уровня TopLevelClass: не вложен (следовательно, он назван не локальным, а не анонимным)
  • Класс второго уровня, класс без имени, который расширяет Clonable и не является членом какого-либо класса: является анонимным (внутренний класс, не являющийся членом, находится в локальной области, но не является "локальный класс" )
  • Класс третьего уровня PrivateInnerClass, член анонимного класса: вложен, не является локальным, не является анонимным, является нестационарным внутренним классом

Вы используете модификатор private в (2). Ваш включенный текст JLS гласит, что это незаконно:

8.1.1

Публичный доступный модификатор доступа (§6.6) относится только к классам верхнего уровня (§7.6) и к классам-членам (§8.5), не к локальным классам (§14.3) или анонимным классы (§15.9.5). Модификаторы доступа, защищенные и приватные (§6.6), относятся только к только к классам-членам внутри объявления с непосредственным включением класса или перечисления (§8.5).

то есть. вы можете использовать ни один из этих модификаторов внутри (в рамках) анонимного класса.


Ответ на дополнительную заметку 2:

В моем понимании, когда класс Identifier представляет собой класс XXX, то, что указано в §8.1.1, ограничивает модификатор Identifier, а не модификаторы в других объявлениях ClassBody идентификатора. В противном случае анонимные классы даже не могут иметь эти поля и методы.

  • Ограничение модификатора перед идентификатором

    • Это указано в 8.1.1. Это явно применимо.
    • Все модификаторы могут применяться перед идентификатором класса-члена
    • public может применяться перед идентификатором класса верхнего уровня
    • Никакие модификаторы не могут применяться перед идентификатором локальных/анонимных классов (классы, объявленные в локальной области)

    Почему это?

    Поскольку классы-члены могут ссылаться непосредственно на другие классы (через "цепочку-член" из класса верхнего уровня), но локальные/анонимные классы никогда нельзя ссылаться снаружи. Локальные/анонимные объявления классов скрыты в области, которая сама недоступна для любой другой части программы Java.

    Модификаторы являются законными только перед объявлением класса, когда объявление доступно для других классов.

  • Ограничение модификатора в ClassBody

    Если идентификатор/декларация класса недоступен для других частей программы Java, конечно, ClassBody также не доступен.

    Следовательно, всякий раз, когда модификатор является незаконным до Идентификатора, модификатор не может иметь возможного семантического значения внутри ClassBody.

    Правила того, разрешен ли модификатор в ClassBody, всегда должны быть идентичны правилам, разрешен ли модификатор до Идентификатора.

  • Итак, 8.1.1. ограничивает модификаторы в обоих местах

:)

Ответ 2

Вы пропустили слово "содержать". PrivateInnerClass является членом вашего анонимного класса и содержится в нем, поэтому он не может иметь модификатор доступа в соответствии с правилом 14.3.

Он может иметь модификаторы доступа для своих собственных членов, но вы этого не исследовали.

Сообщение об ошибке Eclipse неправильно описывает его как локальное.

Вы также пропустили то, что 'private' ничего не добавит, даже если оно было законным, поскольку внутренний класс невидим в любом случае.

Ответ 3

Мой последний ответ состоит из двух тезисов:

  • Не существует сильного объявления ограничений для модификаторов анонимных членов класса в JLS. То есть не существует такой части JLS.

  • Но согласно спецификациям JVM анонимные классы не являются членами класса:

JVM 7 spec: 4.7.6 Атрибут InnerClasses гласит:

Если C не является членом класса или интерфейса (то есть, если C является класс или интерфейс верхнего уровня (JLS §7.6) или локальный класс (JLS §14.3) или анонимный класс (JLS §15.9.5))...

так, согласно

8.5 Объявление типа члена

Класс-член - это класс, декларация которого непосредственно заключена в другое объявление класса или интерфейса.

анонимные классы не являются классами членов.

так, согласно 8.1.1. Модификаторы классов:

Модификаторы доступа, защищенные и приватные (§6.6), относятся только к классы-члены в пределах класса с непосредственным вложением

эти классы не являются классами-членами, поэтому они не могут упоминать модификаторы.