2015-02-09 8 views
18

Java 7 è stato detto "non può fare riferimento al messaggio variabile locale non finale definito in un ambito di inclusione" sul seguente codice:Java fermato erroring su variabili non definitive in classi interne (java 8)

public class Runner { 
    public static void main(String[] args) { 

     String message = "Hello world"; 

     new Runnable() { 
      @Override 
      public void run() { 
       System.out.println(message); 
      } 
     }.run(); 
    } 
} 

Java 8 non lo fa.

Sospetto che si tratta di aggiungere funzionalità di programmazione funzionale a Java.

Elabora il codice in modo simile?

+0

Molto interessante. – vikingsteve

risposta

23

Java 8 rende implicitamente message finale perché non viene mai modificato. Prova a modificarlo ovunque nel tuo codice e otterrai un errore di compilazione (perché rimuove l'implicito final).

Questo è chiamato efficace finale. Citando From the docs:

However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.

+0

Riceverai un errore non appena lo modifichi ovunque (anche all'esterno del Runnable) giusto? – gfkri

+0

Sì, è corretto. Pensalo come un 'finale' invisibile. – Matt

7

Java 8 (e lambda) introducono il termineefficacemente finale: anche se non avete delcare è finale con la parola chiave final, se non viene modificata, è buono come finale .

Citando Oracle Tutorial: Local Classes:

However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.

Il vostro messaggio è effettivamente finale in modo che sia valido per riferirsi ad esso da classi interne anonime e lambda.

Se si modifica il valore del messaggio, non sarà efficacemente finale più:

String message = "Hello world"; 
new Runnable() { 
    @Override 
    public void run() { 
     System.out.println(message); 
    } 
}.run(); 
message = "modified"; 

E quindi si ottiene il seguente errore (da Eclipse):

Local variable message defined in an enclosing scope must be final or effectively final

Or modulo javac:

error: local variables referenced from an inner class must be final or effectively final

2

La variabile message è effectively final. Citando dal riferimento al linguaggio

If a variable is effectively final, adding the final modifier to its declaration will not introduce any compile-time errors.

Quindi, perché message di riferimento non viene modificato da nessuna parte dentro di voi classe interna, il compilatore tratta come efficace finale.

Questo avrebbe gettato errore:

new Runnable() { 
      @Override 
      public void run() { 
       message = "hey"; 
       System.out.println(message); 
      } 
     }.run(); 

La ragione, Java7 compilatore genera l'errore è a causa di un cambiamento di specifiche per lambdas.

Any local variable, formal parameter, or exception parameter used but not Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.

Anonimo Le classi interne e lambda condividono le stesse regole.

2

Sì, lo è.

Fondamentalmente si sono resi conto che il compilatore deve già decidere analizzando il codice quando una variabile locale è "effettivamente finale", cioè il suo valore non viene mai modificato.

Quindi la semantica non è cambiata: anche se non è più necessario dichiarare esplicitamente la variabile final, è necessario accertarsi che non venga mai riassegnata.

+0

Solo una nota a margine: devono * averlo sempre saputo: è esattamente la stessa analisi che ha sfornato gli errori del compilatore "final" dal momento che Java 1.0 :) Ciò che è cambiato nel frattempo è il * spirito di Java * --- una volta una "lingua dei colletti blu" in cui le caratteristiche e le caratteristiche di * erano *, oggi una lingua con serio supporto FP e zucchero sintattico dappertutto. –

+0

@MarkoTopolnik Hai ragione, quello che hanno capito è che possono fare affidamento solo su di esso e non c'è motivo di costringere gli sviluppatori ad aggiungere la parola chiave 'final'. Ma la risposta li aveva guardati in faccia dal primo giorno. – biziclop

Problemi correlati