Perché una variabile finale deve essere inizializzata prima che il costruttore sia completato?
public class Ex { final int q; }
Quando compilo questo codice ottengo un errore come questo
err: la variabile q potrebbe non essere stata inizializzata
Il motivo ufficiale è che è definito da Java Language Spefication 8.3.1.2 :
Una variabile di istanza finale vuota deve essere assegnata definitivamente alla fine di ogni costruttore della class in cui è dichiarata; in caso contrario si verifica un errore in fase di compilazione.
Un finale vuoto è una variabile finale la cui dichiarazione manca di un inizializzatore (cioè ciò che descrivi).
Perché l’ final
impedisce di modificare le variabili, ma deve essere inizializzato ad un certo punto e i costruttori sono il posto giusto per farlo.
Nel tuo caso, si chiamerebbe una finale vuota perché non è inizializzata quando dichiarata.
Il valore di una variabile final
può essere impostato solo una volta. Il costruttore è l’unico posto nel codice per una class che è ansible garantire che sia valido; il costruttore viene chiamato sempre una sola volta per un object, ma altri metodi possono essere chiamati un numero qualsiasi di volte.
Una variabile final
deve essere inizializzata alla dichiarazione o in un costruttore.
Se non è stato inizializzato al ritorno del costruttore, potrebbe non essere mai inizializzato e potrebbe rimanere una variabile non inizializzata. Il compilatore non può dimostrare che verrà inizializzato e genera quindi un errore.
Questo estratto di Wikipedia lo spiega bene:
Una variabile finale può essere inizializzata solo una volta, tramite un inizializzatore o un’istruzione di assegnazione. Non ha bisogno di essere inizializzato al punto di dichiarazione: questo è chiamato una variabile “vuoto finale”. Una variabile di istanza finale vuota di una class deve essere definitivamente assegnata alla fine di ogni costruttore della class in cui è dichiarata; analogamente, una variabile statica finale vuota deve essere assegnata definitivamente in un inizializzatore statico della class in cui è dichiarata: in caso contrario, si verifica un errore in fase di compilazione in entrambi i casi. (Nota: se la variabile è un riferimento, ciò significa che la variabile non può essere rilegata per fare riferimento a un altro object, ma l’object a cui fa riferimento è ancora mutevole, se originariamente era mutabile.)
La parola chiave final
applicata a un campo ha uno dei due effetti:
final HashMap a
, sarà ansible impostarlo solo una volta e non sarà ansible farlo this.a=new HashMap();
di nuovo, ma nulla ti impedisce di fare this.a.put("a","b")
, poiché non modifica il riferimento, ma solo il contenuto dell’object. Il modificatore final
impedisce di modificare il valore delle variabili, quindi devi inizializzarlo dove lo dichiari.
Le specifiche del linguaggio contengono garanzie specifiche sulle proprietà delle variabili e dei campi finali, e una di queste è che un object costruito correttamente (cioè il cui costruttore sia stato completato con successo) deve avere tutti i campi di istanza finali inizializzati e visibili a tutti i thread. Pertanto, il compilatore analizza i percorsi del codice e richiede l’inizializzazione di quei campi.
Final modifier
non consente di change your variable value
. Pertanto, è necessario assegnare un valore ad esso in un determinato punto e in questo caso il constructor
è il punto in cui deve farlo.