Предостережение # 1: это, по сути, потенциальный двухпартер: во-первых, имеет ли конструктор для частного внутреннего класса формальный параметр? Если да, то почему JLS говорит, что нет? А если нет, то как/почему нет?
Предостережение # 2: Этот вопрос не для спекуляций. Я ищу только авторитетные ответы.
Конструкторы по умолчанию определены в JLS 8.8.9, в котором говорится (частично):
Конструктор по умолчанию не имеет формальных параметров, кроме внутреннего класса не private, где конструктор по умолчанию неявно объявляет один формальный параметр, представляющий непосредственно входящий экземпляр класса (§8.8.1, §15.9.2, §15.9.3).
(выделено курсивом)
"Не-частный" бит кажется мне странным: для того, чтобы внутренний класс мог получить доступ к полям, определенным в его охватывающем классе, ему нужна ссылка на этот экземпляр. Это должно быть одинаково независимо от того, является ли внутренний класс закрытым.
На самом деле, javac, похоже, согласен со мной, что противоречит спецификации. Если я скомпилирую это:
public class Ctors {
private class MyInner {
}
}
... и запустите javap -c -private
, тогда мы увидим конструктор с одним формальным параметром для экземпляра охватывающего класса:
$ javap -c -private Ctors\$MyInner
Compiled from "Ctors.java"
class Ctors$MyInner {
final Ctors this$0;
private Ctors$MyInner(Ctors);
Code:
0: aload_0
1: aload_1
2: putfield #1 // Field this$0:LCtors;
5: aload_0
6: invokespecial #2 // Method java/lang/Object."<init>":()V
9: return
}
Для справки, это на Oracle JDK 1.8.0_05.
Итак, JLS говорит, что конструктор по умолчанию для частных внутренних классов-членов не имеет формальных параметров, но javac/javap говорит, что он имеет один. (Мое понимание самого естественного способа для работы на работе также скажет, что оно должно иметь одно, за малое, что стоит.) Что правильно, и почему JLS специально исключает частные внутренние классы?