Das Kapitel über lambda expression bodies heißt
Anders als Code in anonymer Klasse Erklärungen erscheinen, die Bedeutung von Namen und die this
und super
Schlüsselwörter in einem Lambda-Körper, zusammen mit der Zugänglichkeit der referenzierten Erklärungen erscheinen, sind die gleichen wie im umgebenden Kontext (außer, dass Lambda-Parameter einführen neue Namen).
Die Transparenz der this
(explizit oder implizit) in dem Körper eines lambda expression - die, zur Behandlung es die gleichen wie in dem umgebenden Kontext ist - mehr Flexibilität für Implementierungen ermöglicht, und verhindert, dass die Bedeutung von unqualifizierten Namen im Körper von abhängig von Überladung Auflösung.
Sie sind strenger deswegen. Der Umgebungskontext ist in diesem Fall eine Zuweisung zu einem Feld und das vorliegende Problem ist ein Zugriff auf ein Feld val
, ein leeres Feld final
, in der rechten Seite des Ausdrucks.
Die Java Language Specification heißt
Jede lokale Variable (§14.4) und jedes leere Feld final
(§4.12.4, §8.3.1.2) einen eindeutig zugeordneten Wert haben muss, wenn ein Zugriff auf seine Wert tritt auf.
Ein Zugriff auf seinen Wert besteht aus den einfachen Namen der Variablen (oder für ein Feld, das einfache Name des Feldes durch this
qualifiziert) überall in einem Ausdruck auftretenden außer wie der linken Operand von der einfache Zuweisungsoperator =
(§15.26.1).
Für jeden Zugriff auf eine lokale Variable oder leere final
Feld x
muss x
auf jeden Fall vor dem Zugriff zugewiesen sein, oder ein Fehler bei der Kompilierung auftritt.
Es geht dann auf
Lassen C
eine Klasse sein, zu sagen, und lassen Sie V
static
Mitglied Feld in C
von C
, erklärt ein leeres final
nicht sein. Dann gilt:
V
ist auf jeden Fall nicht zugeordneten (und darüber hinaus nicht eindeutig zugeordnet ist) vor der am weitesten links liegende Instanz Initialisierer (§8.6) oder Instanzvariable Initialisierer von C
.
V
ist [un] zugewiesen vor einer Instanz Initialisierer oder Instanzvariable Initialisierer von C
andere als die am weitesten links stehenden iff V
[un] nach dem vorhergehenden Beispiel Initialisierer oder Instanz Variableninitialisierer von C
zugeordnet ist.
Ihr Code sieht im Grunde wie diese
private final int val;
// leftmost instance variable initializer, val still unassigned
private final Callable<String> anonInnerGetValString = ...
// still unassigned after preceding variable initializer
private final Callable<String> lambdaGetValString = ...
Der Compiler bestimmt daher, dass val
in nicht zugeordnet, wenn sie den Zugang innerhalb der Initialisierungsausdruck ist für lambdaGetValString
. Die obigen Regeln gelten für die Verwendung eines einfachen Namens, val
, nicht für einen qualifizierten Ausdruck, this.val
. Sie können
final Callable<String> lambdaGetValString =() -> String.valueOf(this.val);
Verwandte nutzen: http://stackoverflow.com/questions/30130148/reference-to-the-final-field-from-lambda-expression –
Interessanterweise, wenn Sie die 'final' Modifikator entfernen auf 'val' kompiliert es ... – lucasvw
Wenn Sie' String.valueOf (val) 'in' String.valueOf (Immutable.this.val) 'es kompiliert auch – csharpfolk