Рассмотрим этот фрагмент кода:
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
поля и методы членов разрешены.