2015-05-08 5 views
11

Recentemente ho trovato una sottile differenza tra classe anonima ed espressione lambda:riferimento al campo finale da un'espressione lambda

public class FinalTest { 
    final Runnable x = new Runnable() { 
     @Override 
     public void run() { 
      System.out.println(x.hashCode()); 
     } 
    }; 

    final Runnable y =() -> System.out.println(y.hashCode()); 
} 

solito lambda sono equivalenti alle classi anonime. Anche il mio IDE Eclipse ha il refactoring per convertire lo x in lambda (diventa esattamente come) e convertire in classe anonima (diventa esattamente come x). Tuttavia il lambda mi dà un errore di compilazione mentre la classe anonima può essere perfettamente compilata. Il messaggio di errore è simile al seguente:

>javac FinalTest.java 
FinalTest.java:9: error: self-reference in initializer 
    final Runnable y =() -> System.out.println(y.hashCode()); 
               ^
1 error 

Quindi la domanda è: perché c'è questa differenza?

+0

Vorrei, ma non ho JDK 8 sulla mia macchina al momento, motivo per cui l'ho buttato lì. –

+0

@TagirValeev perché non si pubblica il messaggio di errore, invece di costringerci a compilare il codice o indovinare quale può essere il problema? –

+0

@JBNizet, messaggio di errore aggiunto. –

risposta

15

Questo ha a che fare con JLS #8.3.3 che riguarda i riferimenti in avanti. In particolare, se si utilizza un nome completo compila (perché la terza condizione di tale regola diventa falsa L'utilizzo è un nome semplice sia un'istanza inizializzazione variabile di C o un inizializzatore di C esempio):

final Runnable y =() -> System.out.println(this.y.hashCode()); 

Nel caso della classe anonima, la quarta condizione (C è la classe più interna o l'interfaccia che racchiude l'utilizzo) non è vera perché la classe che racchiude è la classe anonima stessa.