Когда внутренние классы были добавлены в Java в версии sion 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
и intialise на 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
.
Для справки [внутренний класс] (http://docs.oracle.com/javase /tutorial/java/javaOO/nested.html). –
Кроме того, я считал, что 'new' является оператором на многих языках. (Я думал, вы также можете перегружать 'new' в C++?) Внутренний класс Java для меня немного странный. –
В StackOverflow нет глупых вопросов! –