Wenn innere Klassen zu Java in ver. Hinzugefügt wurden 1.1 der Sprache wurden sie ursprünglich als eine Umwandlung in 1.0 kompatiblen Code definiert. Wenn Sie sich ein Beispiel dieser Transformation ansehen, wird es meiner Meinung nach viel klarer machen, wie eine innere Klasse tatsächlich funktioniert.
Betrachten Sie den Code aus Ian Roberts' Antwort:
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();
}
}
Wenn auf 1,0 kompatiblen Code transformiert, dass innere Klasse Bar
so etwas wie dieses werden würde:
das Präfix
class Foo$Bar {
private Foo this$0;
Foo$Bar(Foo outerThis) {
this.this$0 = outerThis;
}
public void printVal() {
System.out.println(this$0.val);
}
}
Die innere Klassennamen mit dem Namen der äußeren Klasse, um es einzigartig zu machen. Ein verstecktes privates this$0
Mitglied wird hinzugefügt, das eine Kopie des äußeren this
enthält. Und ein versteckter Konstruktor wird erstellt, um diesen Member zu initialisieren.
Und wenn man sich die Methode createBar
aussehen, wäre es in etwa wie folgt umgewandelt werden:
public Foo$Bar createBar() {
return new Foo$Bar(this);
}
Lassen Sie uns also sehen, was passiert, wenn Sie den folgenden Code ausführen.
Foo f = new Foo(5);
Foo.Bar b = f.createBar();
b.printVal();
Zuerst instanziieren wir eine Instanz von Foo
und intialise die val
Element 5 (das heißt f.val = 5
).
nächst wir f.createBar()
nennen, die eine Instanz von Foo$Bar
und initialisiert das this$0
Elemente auf den Wert des in this
von createBar
(d.h. b.this$0 = f
) geleitet instanziiert.
Schließlich nennen wir b.printVal()
die b.this$0.val
zu drucken versucht, die f.val
ist, die ist 5.
nun, dass eine regelmäßige Instanziierung einer inneren Klasse. Lassen Sie uns sehen, was passiert, wenn Bar
von außerhalb Foo
instanziiert wird.
Foo f = new Foo(5);
Foo.Bar b = f.new Bar();
b.printVal();
unsere 1.0-Transformation wieder anwenden, wäre die zweite Linie etwas so worden:
Foo$Bar b = new Foo$Bar(f);
Dies ist fast identisch mit dem f.createBar()
Anruf. Erneut instanziieren wir eine Instanz von Foo$Bar
und initialisieren das Element this$0
für f. Also nochmal, b.this$0 = f
.
Und wieder, wenn Sie b.printVal()
nennen, drucken Sie b.thi$0.val
die f.val
ist die 5. ist
Der Schlüssel ist daran zu erinnern ist, dass die innere Klasse ein verborgenes Element eine Kopie von this
von der äußeren Klasse zu halten. Wenn Sie eine innere Klasse aus der äußeren Klasse instanziieren, wird sie implizit mit dem aktuellen Wert this
initialisiert. Wenn Sie die innere Klasse von außerhalb der äußeren Klasse instanziieren, geben Sie über das Präfix new
explizit an, welche Instanz der äußeren Klasse verwendet werden soll.
für Ihre Referenz, [innere Klasse] (http://docs.oracle.com/javase /tutorial/java/javaOO/nested.html). –
Ich hatte auch geglaubt, dass "neu" ein Operator in vielen Sprachen ist. (Ich dachte, Sie könnten auch "neu" in C++ überladen?) Javas innere Klasse ist für mich ein bisschen komisch. –
Es gibt keine dummen Fragen zu StackOverflow! –