Der Compiler generiert automatisch einen Konstruktor für Ihre anonyme innere Klasse und übergibt Ihre lokale Variable an diesen Konstruktor.
Der Konstruktor speichert diesen Wert in einer Klassenvariablen (einem Feld), auch i
genannt, die innerhalb der "Schließung" verwendet wird.
Warum muss es endgültig sein? Nun lassen Sie uns die Situation erkunden in denen es nicht:
public class A {
public void method() {
int i = 0; // note: this is WRONG code
doStuff(new Action() {
public void doAction() {
Console.printf(i); // or whatever
}
});
i = 4; // A
// B
i = 5; // C
}
}
In Situation A das Feld i
von Action
auch geändert werden muss, nehmen wir an, dies ist möglich: es muss die Referenz auf das Objekt Action
.
Angenommen, in Situation B ist diese Instanz von Action
Müll gesammelt.
Jetzt in Situation C: es benötigt eine Instanz von Action
, um seine Klassenvariable zu aktualisieren, aber der Wert ist GCed. Es muss "wissen", dass es GCed ist, aber das ist schwierig.
Um die Implementierung der VM zu vereinfachen, haben die Java-Sprachentwickler gesagt, dass sie endgültig sein sollten, so dass die VM keine Möglichkeit zum Überprüfen, ob ein Objekt verschwunden ist, und garantiert, dass die Variable nicht ist modifiziert, und dass die VM oder der Compiler nicht alle Verwendungen der Variablen in anonymen inneren Klassen und deren Instanzen referenzieren muss.
Eigentlich die synthetisierte Variable, die eine Kopie der Variablen hält i nicht genannt. Abhängig davon, welche Version des Compilers Sie verwenden, ist es "$ i" oder "+ i". –