2014-10-27 17 views
5

Vor Java 8 konnte eine innere Klasse nur auf äußere Objekte zugreifen, wenn sie als final deklariert wurden. Aber jetzt, wenn ich Beispielcode (von unten) auf JavaSE 1.8 ausführen, gibt es keinen Kompilierungsfehler und Programm läuft gut.Anonyme Klassen können auf nicht-finale äußere Objekte in Java 8 zugreifen?

Warum haben sie das geändert und wie funktioniert es jetzt?

Beispiel-Code von Java 7 Tutorial:

public class MOuter { 
    private int m = (int) (Math.random() * 100); 

    public static void main(String[] args) { 
     MOuter that = new MOuter(); 
     that.go((int) (Math.random() * 100), (int) (Math.random() * 100)); 
    } 

    public void go(int x, final int y){ 
     int a = x + y; 
     final int b = x - y; 

     class MInner{ 
      public void method(){ 
       System.out.println("m is "+m); 
       System.out.println("x is "+x); // supposedly illegal - 'x' not final 
       System.out.println("y is: "+y); 
       System.out.println("a is "+a); // supposedly illegal? - 'a' not final 
      } 
     }  
     MInner that = new MInner(); 
     that.method(); 
    } 
} 
+1

Was JB sagte. Es ist jetzt "effektiv endgültig". Es wurde hinzugefügt, um lambdas in Java 8 besser zu unterstützen (die wie Verschlüsse sind, aber ein wenig anders). – markspace

+2

[Unterschied zwischen final und effektiv final] (http://stackoverflow.com/questions/20938095/difference-between-final-and-effectively-final) – alex

Antwort

7

In Java 7 die das Konzept der effektiv endgültige eingeführt wurde die "more precise rethrow" feature zu unterstützen, und ihr Umfang wurde in Java 8 erweitert lokale Variablen zu decken, die nur einmal vergeben werden, aber nicht wirklich final. erklärt Diese erfasst werden können und in Lambda-Körpern oder innere Klassen verwendet, als ob sie wurden final. erklärt

Das in section §4.12.4 der Java Language Specification bedeckt ist:

Bestimmte Variablen, die nicht 0.123.650 deklariert werdenkann stattdessen betrachtet werden effektiv endgültig.

Eine lokale Variable oder ein Verfahren, Konstruktor, Lambda, oder ausgenommen Parameter sind effektiv endgültigen wenn es nicht erklärt final wird, aber es tritt nie als der linke Operand eines Zuweisungsoperators (§15.26) oder als der Operand eines Präfix- oder Postfixinkrements oder Dekrementoperator (§15.14, §15.15).

Zusätzlich kann eine lokale Variable, deren Erklärung fehlt ein initializer ist effektiv endgültig, wenn alle folgenden Bedingungen erfüllt sind:

  • Es ist nicht final.

  • erklärt Wann immer es auftritt als der linke Operand einer Zuweisung Operator, es ist definitiv nicht zugewiesen und nicht eindeutig zugeordnet vor der Zuweisung; das heißt, es ist definitiv nicht zugewiesen und nicht definitiv zugewiesen nach dem rechten Operanden der Zuweisung (§16 (Definite Assignment)).

  • Es tritt nie als Operand eines Präfix oder Postfix Inkrement oder Dekrement-Operator.

Wenn eine Variable effektiv endgültig ist, Hinzufügen des final Modifikator auf seine Erklärung wird keine Kompilierung-Fehler einführen.Umgekehrt wird eine lokale Variable oder ein lokaler Parameter, der in einem gültigen Programm final als deklariert ist, effektiv final, wenn der Modifikator final entfernt wird.

+3

Eigentlich wurde der Begriff von * effektiv final * in Java 7 hinzugefügt, und in der Funktion "Präzisere Neuausgabe" verwendet. Sein Anwendungsbereich wurde in Java 8 erweitert, um lokale Variablen abzudecken, die von Lambdas oder inneren Klassen erfasst werden. –

+1

Danke, @Brian! Ich habe meine Antwort aktualisiert, um das zu reflektieren. –

3

Es ist immer noch die gleiche Regel, mit der Ausnahme der Compiler dich nicht zwingen, explizit die Variable als final mehr zu definieren. Wenn es effektiv endgültig ist, können Sie darauf zugreifen. Wenn dies nicht der Fall ist (d. H. Der Compiler erkennt, dass die Variable neu zugewiesen wird), wird nicht kompiliert.

Verwandte Themen