Eine nicht abschließende Elementvariable wird immer initialisiert (da sie im Fall Ihrer String
Variable einen Standardwert hat - null
), es besteht also keine Möglichkeit, dass sie nicht initialisiert wird.
Auf der anderen Seite kann eine letzte Variable nur einmal initialisiert werden, also gehe ich davon aus, dass sie nicht auf ihren Standardwert initialisiert wird.
Die am engsten verwandten, was ich gefunden ist in JLS 4.12.4.:
4.12.4. final Variables
A variable can be declared final. A final variable may only be assigned to once. It is a compile-time error if a final variable is assigned to unless it is definitely unassigned immediately prior to the assignment
Ich gehe davon aus wir diesen letzten Satz zu verstehen, verstehen, dass eine endgültige Variable keinen Standardwert zugewiesen wird, da sonst finden Sie eine Kompilierung erhalten Zeitfehler bei this.s = s;
.
Eine bessere JLS Referenz (dank Holger) ist JLS 16:
Chapter 16. Definite Assignment
For every access of a local variable or blank final field x, x must be definitely assigned before the access, or a compile-time error occurs.
Die rationale hinter dieser Forderung ist, dass (in Ihrem Beispiel) der Lambda-Ausdruck vor s
aufgerufen werden kann initialisiert:
public A(String s) {
String v = f.apply("x"); // this.s is not initialized at this point
// so it can't be accessed
this.s = s;
}
Beachten Sie, dass Sie den Lambda-Ausdruck im Konstruktor initialisieren können, nachdem Sie die letzte Variable initialisiert haben (ich änderte den Namen des Arguments anders als die Elementvariable, so dass der Lambda-Ausdruck nicht gr ab, dass die lokale Variable):
public A(String so) {
// f = e -> s; // Error: The blank final field s may not have been initialized
this.s = so;
f = e -> s; // works fine
}
Es ist eine fundamentale Eigenschaft der Lambda-Ausdrücke, wie Ausdrücke im umgebenden Kontext zu arbeiten, so dass die Regeln bezüglich des Zugriffs auf leere finale Variablen gleich sind. Dies ist anders als innere Klassen. Beachten Sie, dass Sie anstelle von 'getA() '' auch umgehen können, indem Sie 'Test.this.a' verwenden, um auf' a' zuzugreifen. – Holger
@Holger Danke, die Antworten, die Sie verlinkt haben, sind sehr interessant und klar. Interessant, dass der Zugriff auf "a" über "a" und "this.a" Fehler sind, aber "Test.this.a" ist kein Fehler im Falle des Lambda, aber immer noch ein Fehler im Falle der Zuweisung zu "b". –
Ich habe 'b = Test.this.a;' mit fast jedem JDK 8 & 9 versucht und es hat funktioniert. [Die Spezifikation] (https://docs.oracle.com/javase/specs/jls/se8/html/jls-16.html) bezieht sich eindeutig auf "* den einfachen Namen der Variablen (oder, für ein Feld, die einfacher Name des Felds, das durch 'this' qualifiziert wurde) * "wenn der Zugriff auf eine leere letzte Variable verboten wird. Hast du Eclipse benutzt? – Holger