2016-10-06 3 views
1

Inner Klassen haben nur Zugriff auf endgültige oder effektiv endgültige Variablen. Ich verstehe jedoch nicht, warum auf eine Instanzvariable zugegriffen werden kann, egal wie, aber lokale Variablen und Methodenparameter müssen minimal effektiv sein?Effektiv final - Inner Klassen Zugriff

Betrachten Sie den folgenden Code ein:

public class BookStore { 

    private static final int taxId = 300000; 
    public String name; 

    public String searchBook(final String criteria) {  
     int count = 0;  
     int sum = 0;  
//  name = "";  I can uncomment this -> no compile error 
     class Enumerator {   
      String interate(int k) {  
       System.out.println(name); 
       System.out.println(sum); 
       return "";   
      }    
     }    
//  sum++;  If I uncomment this, a compile error will be thrown. 
     return ""; 
    } 

} 

Warum ist es notwendig, dass die lokalen Variablen + Methodenargumente effektiv endgültig sein müssen?

Antwort

1

Es liegt am Umfang der lokalen Variablen. Ihr Anwendungsbereich ist die Methode, in der sie erklärt werden. Sobald die Ausführung die Methode verlassen hat, sind sie nicht mehr gültig. Eine innere Klasse wie Ihre Enumerator-Klasse kann jedoch nach der Ausführung der Methode weiter bestehen, z. indem Sie einen Verweis auf eine Klasseninstanz zurückgeben.

Somit kann auf die Enumerator-Klasse und ihre Methoden außerhalb der Methode, in der sie deklariert ist, zugegriffen werden. An diesem Punkt muss davon ausgegangen werden, dass die lokalen Variablen, auf die sie verwiesen wird, denselben Wert haben, den sie hatten, als die Ausführung die Klasse instanziiert hat.

Zum Beispiel Variablen, der Geltungsbereich dieser und der inneren Klasse ist gleich - sie sind beide verfügbar, solange die Elternklasseninstanz existiert.

+0

Was meinst du mit „der Enumerator-Klasse außerhalb zugegriffen werden kann“? – codepleb

+0

Es kann nicht mit dem genauen Code, den Sie geschrieben haben, aber der Compiler berücksichtigt die theoretische Möglichkeit, die es könnte. Sie könnten etwas wie neue Enumerator(); Das würde einen Verweis auf ein Enumerator-Objekt an den äußeren Bereich übergeben. –

+0

Das geht nicht, wenn ich mich nicht irre. Ich kann den Typ "Enumerator" mit dieser Methode nicht zurückgeben, da der Compiler diesen Typ nicht kennt, wenn Sie ihn in der Methode angeben. – codepleb

1

Es ist alles über den Wert erfasst, wenn die Instanz erstellt wird. Innere Klassen in einem Instanzkontext erfassen immer die unveränderliche äußere this Referenz¹, über die auf die Instanzfelder zugegriffen werden kann, veränderbar oder nicht. Im Gegensatz dazu können lokale Variablen nur durch ihren Wert erfasst werden. Daher darf sich die Variable nicht ändern, um mit dem erfassten Wert konsistent zu sein.

Dies ist eine Designentscheidung. Technisch wäre es kein Problem, a) nachfolgende Mutationen zuzulassen, die nicht vom inneren Klassenzustand reflektiert werden, oder b) jede gemeinsam genutzte lokale Variable in ein Objekt zu wickeln, um Mutationen wie bei Instanzfeldern der äußeren Klasse, aber auch nicht erlaubt zuzulassen Inkonsistenz oder lokale Variablen, die nicht lokal sind, wurden von den Sprachdesignern als akzeptabel erachtet.

¹ Diese von Lambda-Ausdrücke unterscheidet, die nur this erfassen, wenn tatsächlich Instanzvariablen Zugriff auf

Verwandte Themen