Коли внутрішні класи були додані до Java у версії 1.1 мови, вони спочатку були визначені як перетворення на 1.0 сумісний код. Якщо ви подивитесь на приклад цієї трансформації, я думаю, це зробить набагато зрозумілішим, як насправді працює внутрішній клас.
Розглянемо код з відповіді Яна Робертса:
public class Foo {
int val;
public Foo(int v) { val = v; }
class Bar {
public void printVal() {
System.out.println(val);
}
}
public Bar createBar() {
return new Bar();
}
}
При перетворенні на 1.0 сумісний код цей внутрішній клас Barстав би приблизно таким:
class Foo$Bar {
private Foo this$0;
Foo$Bar(Foo outerThis) {
this.this$0 = outerThis;
}
public void printVal() {
System.out.println(this$0.val);
}
}
Ім’я внутрішнього класу є префіксом зовнішнього імені класу, щоб зробити його унікальним. Додано прихований приватний this$0член, який містить копію зовнішнього this. І прихований конструктор створюється для ініціалізації цього члена.
А якщо поглянути на createBarметод, він би перетворився на щось подібне:
public Foo$Bar createBar() {
return new Foo$Bar(this);
}
Тож давайте подивимося, що станеться при виконанні наступного коду.
Foo f = new Foo(5);
Foo.Bar b = f.createBar();
b.printVal();
Спочатку ми інстанціюємо екземпляр Fooта інциліфікуємо valчлена до 5 (тобто f.val = 5).
Далі ми викликаємо f.createBar(), який інстанціює екземпляр Foo$Barі ініціалізує this$0члена до значення thisпереданого з createBar(тобто b.this$0 = f).
Нарешті ми називаємо, b.printVal()хто намагається надрукувати b.this$0.val, f.valякий є 5.
Тепер це була регулярна інстанція внутрішнього класу. Давайте подивимось, що відбувається при інстанції Barззовні Foo.
Foo f = new Foo(5);
Foo.Bar b = f.new Bar();
b.printVal();
Знову застосувавши перетворення 1.0, другий рядок став би таким:
Foo$Bar b = new Foo$Bar(f);
Це майже ідентично f.createBar()дзвінку. Знову ми створюємо екземпляр Foo$Barі ініціалізуємо this$0члена до f. Отже, знову b.this$0 = f.
І знову, коли ви телефонуєте b.printVal(), ви друкуєте b.thi$0.val, f.valяка є 5.
Ключове, що потрібно пам’ятати, - це те, що у внутрішньому класі є прихований член, у якому зберігається копія thisзовнішнього класу. Коли ви створюєте внутрішній клас із зовнішнього класу, він неявно ініціалізується з поточним значенням this. Коли ви створюєте екземпляр внутрішнього класу поза зовнішнім класом, ви чітко вказуєте, який екземпляр зовнішнього класу використовувати, за допомогою префікса newключового слова.