Il capitolo sulla lambda expression bodies afferma
A differenza di codice appaiono nelle dichiarazioni di classe anonimi, il significato di nomi e la this
e super
le parole chiave che appaiono in un corpo lambda, insieme con l'accessibilità delle dichiarazioni di riferimento, sono gli stessi come nel contesto circostante (eccetto che i parametri lambda introducono i nuovi nomi ).
La trasparenza this
(esplicite ed implicite) nel corpo di un'espressione lambda - cioè trattando lo stesso come nella contesto circostante - consente maggiore flessibilità per implementazioni, e impedisce sensi qualificato i nomi nel corpo da dipendono dalla risoluzione di sovraccarico.
Sono più severi per questo.
Il contesto circostante, in questo caso, è un'assegnazione a un campo e il problema in questione è un accesso di un campo, val
, un campo vuoto final
, nella parte destra dell'espressione.
Il linguaggio Java Specification afferma
Ogni variabile locale (§14.4) ed ogni vuoto final
campo (§4.12.4, §8.3.1.2) deve avere un valore decisamente assegnato quando qualsiasi accesso del suo valore si verifica.
Un accesso al suo valore consiste nella semplice nome della variabile (o, per un campo, il semplice nome del campo qualificato da this
) verificano ovunque in un'espressione eccetto come operando sinistro di l'operatore di assegnazione semplice =
(§15.26.1).
Per ogni accesso di una variabile locale o vuoto final
campo x
, x
deve essere definitivamente assegnato prima che l'accesso, o in fase di compilazione si verifica un errore.
Si passa poi a dire
Diamo C
essere una classe, e sia V
essere un vuoto final
non static
campo membro di C
, ha dichiarato in C
. Poi:
V
è sicuramente non assegnato (ed inoltre non è sicuramente assegnato) prima della sinistra esempio inizializzatore (§8.6) o istanza variabile inizializzatore di C
.
V
è [un] assegnato prima un inizializzatore istanza o un'istanza inizializzazione variabile C
diversa dalla sinistra sse V
è [un] assegnato dopo il precedente esempio inizializzatore o un'istanza inizializzazione variabile C
.
il codice sia sostanzialmente in questo modo
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 = ...
Il compilatore determina, pertanto, che in val
assegnato quando è accesso all'interno dell'espressione di inizializzazione per lambdaGetValString
.
Le regole sopra riportate si applicano all'uso di un nome semplice, val
, non a un'espressione qualificata, this.val
. È possibile utilizzare
final Callable<String> lambdaGetValString =() -> String.valueOf(this.val);
correlati: http://stackoverflow.com/questions/30130148/reference-to-the-final-field-from-lambda-expression –
È interessante notare che, se si rimuove il modificatore 'final' su 'val' compila ... – lucasvw
Quando cambi' String.valueOf (val) 'in' String.valueOf (Immutable.this.val) 'compila anche – csharpfolk