Perché una variabile finale deve essere inizializzata prima che il costruttore sia completato?

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:

  • su una primitiva, impedisce che il valore della primitiva venga modificato (un int non può modificare il valore)
  • su un object, impedisce che il “valore della variabile”, ovvero il riferimento all’object, venga modificato. Ciò significa che, se si dispone di un 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.