2012-04-26 18 views
46

Der folgende Code in Java verwendet final Array von String und es gibt keine Frage.letzte Array in Java

final public class Main { 
    public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"}; 

    public static void main(String[] args) { 
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) { 
     System.out.print(CONSTANT_ARRAY[x] + " "); 
    } 
    } 
} 

Es zeigt die folgende Ausgabe auf der Konsole an.

I can never change 

Der folgende Code ohne Frage geht auch.

final public class Main { 
    public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"}; 

    public static void main(String[] args) { 
    //CONSTANT_ARRAY={"I", "can", "never", "change"}; //Error - can not assign to final variable CONSTANT_ARRAY. 
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) { 
     System.out.print(CONSTANT_ARRAY[x] + " "); 
    } 
    } 
} 

Offensichtlich ist die Kommentarzeile bewirkt, dass der angegebene Fehler, weil wir versuchen, die erklärt final Array vom Typ String neu zuzuweisen.


Was ist mit dem folgenden Code.

final public class Main { 
    public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"}; 

    public static void main(String[] args) { 
    CONSTANT_ARRAY[2] = "always"; //Compiles fine. 
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) { 
     System.out.print(CONSTANT_ARRAY[x] + " "); 
    } 
    } 
} 

und es zeigt I can always change bedeutet, dass wir String den Wert des final Array vom Typ ändern verwalten zu können. Können wir das gesamte Array auf diese Weise ändern, ohne gegen die Regel final zu verstoßen?

Antwort

75

final in Java beeinflusst die Variable, es hat nichts mit dem Objekt zu tun, das Sie ihm zuweisen.

final String[] myArray = { "hi", "there" }; 
myArray = anotherArray; // Error, you can't do that. myArray is final 
myArray[0] = "over"; // perfectly fine, final has nothing to do with it 

Bearbeiten Kommentare hinzufügen: Bitte beachte, dass ich sagte Objekt, das Sie es zuweisen. In Java ist ein Array ein Objekt. Das gleiche gilt für jedes andere Objekt:

final List<String> myList = new ArrayList<String>(): 
myList = anotherList; // error, you can't do that 
myList.add("Hi there!"); // perfectly fine. 
+3

Sie sagte _object_, und das ist gut dies für alle Objekte gilt, nicht nur Arrays Es ist in Ordnung Objekte zu ändern, sind.. auch der Wert der finalen Variablen, zB final Liste list = new ArrayList (); list.add ("foo"); '. –

9

Sie können nur festlegen, dass die Array-Referenz nicht geändert werden kann. Wenn Sie möchten, dass die Elemente nicht geändert werden können, müssen Sie eine nicht änderbare Sammlung verwenden.

3

Wenn Sie ein Array als final deklarieren, können Sie die Elemente in der Anordnung ändern, jedoch können Sie nicht die Referenz dieses Arrays ändern.

+1

Danke für die einfache Erklärung in einer Zeile. – napender

1

Der Wert der Variablen CONSTANT_ARRAY kann nicht geändert werden. Diese Variable enthält ein (Bezug auf ein) Array. Jedoch kann der Inhalt des Arrays ändern. Das Gleiche passiert, wenn Sie eine beliebige letzte Variable deklarieren, die kein einfacher Skalartyp ist (z. B. ein Objekt).

Seien Sie vorsichtig, wie Sie Ihre Variablen benennen. :-) Der Aufruf eines CONSTANT_ARRAY macht den Inhalt des Arrays nicht veränderbar.

Hier ist eine gute Referenz: The final word on final

2

endgültig garantiert nur Unveränderlichkeit von Primitiven. Und garantiert auch, dass eine Variable nur einmal vergeben wird. Wenn ein Objekt veränderbar ist, können Sie den Inhalt des Ereignisses, das es als endgültig definiert hat, ändern. Sie können unveränderliche Sammlungen für Ihre Bedürfnisse überprüfen. Wie zB Collections.unmodiableList() http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#unmodifiableList(java.util.List)

+2

Nicht der zweite Satz impliziert die erste? – delnan

+0

Nein. Eine Variable kann sich auf eine Objektreferenz beziehen, nicht unbedingt eine Prim itive. – afsina

+1

Ja, na und? Variablen sind Variablen, egal ob sie vom primitiven Typ oder vom Referenztyp sind. In beiden Fällen kann es nicht neu zugewiesen werden. – delnan

13

Sie interpretieren die endgültige Implementierung falsch.final gilt für die Array-Objektreferenz, was bedeutet, dass die Referenz, sobald sie einmal initiiert wurde, sich niemals ändern kann, aber das Array selbst kann ausgefüllt werden. "Es verstößt nicht gegen die Regeln" Sie haben nur eine Regel für die Referenzänderung angegeben, die entsprechend funktioniert. Wenn Sie die Werte wollen, sollten auch Sie sollen nie für Immutable Listen

dh
List<String> items = Collections.unmodifiableList(Arrays.asList("I", "can", "never", "change")); 
2

Der Verweis auf das Array-Objekt gehen ändern ist endgültig (nicht zB im Fall ändern Sie ein anderes Java-Array-Objekt zu verknüpfen versuchen würden (Instanz von String []) auf dieselbe Endvariable ... Sie würden einen Kompilierzeitfehler bekommen).

ABER die Felder der endgültigen Array-Objekt in Ihrem Beispiel sind nicht endgültig, und so können Sie ihren Wert ändern. ... während das von Ihnen erstellte Java-Objekt CONSTANT_ARRAY nach Erhalt eines Anfangswerts den Wert "forever" == hat, bis die JVM beendet wird. :) Es wird die gleiche String-Array-Instanz "für immer" sein.

Endgültige Variablen in Java sind keine große Sache, verbringen Sie einfach etwas Zeit, um das Thema/die Idee sorgfältig zu verarbeiten. :-)
Ich schlage vor, diejenigen zu allen, die unsicher sind, über diese Seite zu meditieren, zum Beispiel: https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4

Lassen Sie mich den jeweiligen Teil zitieren:

" Sobald eine abschließende Variable war Wenn eine letzte Variable einen Verweis auf ein Objekt enthält, dann kann der Zustand des Objekts durch Operationen am Objekt geändert werden, aber die Variable bezieht sich immer auf dasselbe Objekt.

Dies gilt auch für Arrays, weil Arrays sind Objekte; Wenn eine letzte Variable einen Verweis auf ein Array enthält, können die Komponenten des Arrays durch Operationen auf dem Array geändert werden, aber die Variable bezieht sich immer auf das gleiche Array. "

0
final int[] res; 
    int[] res1; 
    int[] res2 = new int[1]; 
    res2[0]=20; 

    res1=res2; 
    res1=res2;//no error 
    System.out.println("res1:"+res1[0]); 

    res = res2;//only once 
    //res = res2;//error already initialised 
    res2[0]=30; 

    System.out.println("res:"+res[0]);  

Ausgang :: res1: 20 res: 30

+1

Das Posten eines Stücks Code stimmt nicht wirklich mit dem Geist des Stapelüberlaufs überein. Bitte antworten Sie mit Inhalt, Kontext und Details. – Gyan