Внутренние классы поддерживают ссылку на внешний экземпляр (исключение составляют static
внутренних классов). В этом случае экземпляр WithInner.Inner
имеет ссылку на содержащий WithInner
экземпляр. Эта ассоциация создается, когда создается внутренний класс.
Вы не можете создать экземпляр внутреннего класса без ссылки на внешний класс. Класс, который расширяет такой внутренний класс, также подразумевает такую ссылку и должен делегировать внутреннему конструктору класса, чтобы установить связь. Синтаксис для этого, что, как показано в вашем примере:
wi.super();
Здесь super()
в основном относится к конструктору суперкласса - то есть, WithInner.Inner
конструктор. Конструктор не принимает никаких параметров формально, но ему все еще нужна ссылка на внешний экземпляр (типа WithInner
). Строка в целом по существу означает «вызывать конструктор суперкласса и ассоциировать с экземпляром wi
».
Сравните с синтаксисом для конкретизации внутреннего класса с явной ассоциации:
wi.new WithInner.Inner()
Да, это справедливо и синтаксис. Однако это обычно не встречается в дикой природе (поскольку внутренние экземпляры классов обычно создаются только из внешнего класса, и в этом случае ассоциация неявно - в этом случае нет необходимости в этом синтаксисе, который явно обеспечивает ассоциацию) ,
С конкретной ссылкой на ваш вопрос:
Я не могу понять, почему мы не можем назвать Wi = новый WithInner(); вместо .super()?
Это не связывает созданный экземпляр WithInner
с экземпляром внутреннего класса. Вы получите ошибку времени компиляции, потому что ваш конструктор InheritInner
больше не будет явно вызывать синтезированный конструктор суперкласса, и его нельзя назвать неявным, потому что ему нужна ссылка внешнего экземпляра для ассоциации. Вероятно, проще всего рассматривать ссылку внешнего экземпляра как скрытый параметр для внутреннего конструктора классов (действительно, так оно реализуется под капотом).
И при вызове wi.super() мы вызываем конструктор по умолчанию Object, не так ли?
Нет, вы вызываете конструктор WithInner.Inner
, который имеет «скрытый» параметр для ссылки внешнего экземпляра; wi
по существу передается в конструктор WithInner.Inner
в качестве значения скрытого параметра.
Странный код еще компилирует ... – h22
'wi = new WithInner();' создаст новый объект 'WithInner', но ничего не сделает с тем, который задан конструктору. –
@ammoQ нет, он не смог бы скомпилировать.См. Мой ответ ниже. – davmac