Ferma la riassegnazione di una variabile
Mentre queste risposte sono intellettualmente interessanti, non ho letto la breve risposta semplice:
Utilizzare la parola chiave final quando si desidera che il compilatore impedisca di riassegnare una variabile a un oggetto diverso.
Che la variabile sia una variabile statica, una variabile membro, una variabile locale o una variabile argomento / parametro, l'effetto è completamente lo stesso.
Esempio
Vediamo l'effetto in azione.
Considera questo semplice metodo, in cui alle due variabili ( arg e x ) è possibile assegnare nuovamente oggetti diversi.
// Example use of this method:
// this.doSomething( "tiger" );
void doSomething( String arg ) {
String x = arg; // Both variables now point to the same String object.
x = "elephant"; // This variable now points to a different String object.
arg = "giraffe"; // Ditto. Now neither variable points to the original passed String.
}
Contrassegna la variabile locale come finale . Ciò provoca un errore del compilatore.
void doSomething( String arg ) {
final String x = arg; // Mark variable as 'final'.
x = "elephant"; // Compiler error: The final local variable x cannot be assigned.
arg = "giraffe";
}
Contrassegniamo invece la variabile del parametro come finale . Anche questo provoca un errore del compilatore.
void doSomething( final String arg ) { // Mark argument as 'final'.
String x = arg;
x = "elephant";
arg = "giraffe"; // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
}
Morale della storia:
Se vuoi assicurarti che una variabile punti sempre sullo stesso oggetto, segna la variabile finale .
Non riassegnare mai argomenti
Come buona pratica di programmazione (in qualsiasi lingua), non si dovrebbe mai riassegnare una variabile parametro / argomento a un oggetto diverso dall'oggetto passato dal metodo chiamante. Negli esempi sopra, non si dovrebbe mai scrivere la riga arg =
. Poiché gli umani commettono errori e i programmatori sono umani, chiediamo al compilatore di aiutarci. Contrassegna ogni variabile parametro / argomento come 'finale' in modo che il compilatore possa trovare e contrassegnare tali riassegnazioni.
Ripensandoci
Come notato in altre risposte ... Dato l'obiettivo di progettazione originale di Java di aiutare i programmatori a evitare errori stupidi come leggere oltre la fine di un array, Java avrebbe dovuto essere progettato per imporre automaticamente tutte le variabili di parametro / argomento come "finale". In altre parole, gli argomenti non dovrebbero essere variabili . Ma il senno di poi è una visione 20/20, e i designer Java avevano le mani piene al momento.
Quindi, aggiungere sempre final
a tutti gli argomenti?
Dovremmo aggiungere final
a ogni singolo parametro del metodo dichiarato?
- In teoria si.
- In pratica, no.
➥ Aggiungi final
solo quando il codice del metodo è lungo o complicato, dove l'argomento può essere scambiato per una variabile locale o membro ed eventualmente riassegnato.
Se acquisti nella pratica di non riassegnare mai un argomento, sarai propenso ad aggiungere un final
a ciascuno. Ma questo è noioso e rende la dichiarazione un po 'più difficile da leggere.
Per un breve codice semplice in cui l'argomento è ovviamente un argomento e non una variabile locale né una variabile membro, non mi preoccupo di aggiungere il final
. Se il codice è abbastanza ovvio, senza alcuna possibilità per me né per nessun altro programmatore che fa manutenzione o refactoring che confonde accidentalmente la variabile argomento come qualcosa di diverso da un argomento, allora non preoccuparti. Nel mio lavoro, aggiungo final
solo nel codice più lungo o più coinvolto in cui un argomento potrebbe essere scambiato per una variabile locale o membro.
Un altro caso aggiunto per la completezza
public class MyClass {
private int x;
//getters and setters
}
void doSomething( final MyClass arg ) { // Mark argument as 'final'.
arg = new MyClass(); // Compiler error: The passed argument variable arg cannot be re-assigned to another object.
arg.setX(20); // allowed
// We can re-assign properties of argument which is marked as final
}