Dobbiamo distinguere due aspetti delle costanti:
- nomi per valori noti in fase di sviluppo, che introduciamo per una migliore manutenibilità, e
- valori disponibili per il compilatore.
E poi c'è un terzo tipo correlato: variabili il cui valore non cambia, ovvero i nomi per un valore. La differenza tra queste variabili immutabili e una costante è quando il valore viene determinato / assegnato / inizializzato: una variabile viene inizializzata in fase di esecuzione, ma il valore di una costante è noto durante lo sviluppo. Questa distinzione è un po 'confusa poiché un valore può essere conosciuto durante lo sviluppo ma in realtà viene creato solo durante l'inizializzazione.
Ma se il valore di una costante è noto al momento della compilazione, il compilatore può eseguire calcoli con quel valore. Ad esempio, il linguaggio Java ha il concetto di espressioni costanti . Un'espressione costante è qualsiasi espressione che consiste solo di letterali di primitive o stringhe, operazioni su espressioni costanti (come casting, addizione, concatenazione di stringhe) e di variabili costanti. [ JLS §15.28 ] Una variabile costante è una final
variabile inizializzata con un'espressione costante. [JLS §4.12.4] Quindi per Java, questa è una costante di compilazione:
public static final int X = 7;
Ciò diventa interessante quando una variabile costante viene utilizzata in più unità di compilazione e quindi la dichiarazione viene modificata. Ritenere:
Ora quando compiliamo questi file il B.class
bytecode dichiarerà un campo Y = 9
perché B.Y
è una variabile costante.
Ma quando cambiamo la A.X
variabile in un valore diverso (diciamo, X = 0
) e ricompiliamo solo il A.java
file, allora facciamo B.Y
ancora riferimento al vecchio valore. Questo stato non A.X = 0, B.Y = 9
è coerente con le dichiarazioni nel codice sorgente. Buon debug!
Ciò non significa che le costanti non debbano mai essere modificate. Le costanti sono decisamente migliori dei numeri magici che compaiono senza spiegazioni nel codice sorgente. Tuttavia, il valore delle costanti pubbliche fa parte dell'API pubblica . Questo non è specifico di Java, ma si verifica anche in C ++ e in altri linguaggi con unità di compilazione separate. Se si modificano questi valori, sarà necessario ricompilare tutto il codice dipendente, ovvero eseguire una compilazione pulita.
A seconda della natura delle costanti, potrebbero aver portato a ipotesi errate da parte degli sviluppatori. Se questi valori vengono modificati, potrebbero attivare un bug. Ad esempio, un insieme di costanti può essere scelto in modo da formare determinati schemi di bit, ad es public static final int R = 4, W = 2, X = 1
. Se questi vengono modificati per formare una struttura diversa come R = 0, W = 1, X = 2
allora il codice esistente come boolean canRead = perms & R
diventa errato. E pensa solo al divertimento che ne deriverebbe se Integer.MAX_VALUE
cambiassero! Non c'è soluzione qui, è importante ricordare che il valore di alcune costanti è davvero importante e non può essere modificato semplicemente.
Ma per la maggior parte delle costanti cambiarle andrà bene fintanto che saranno considerate le restrizioni di cui sopra. Una costante è sicura da cambiare quando il significato, non il valore specifico è importante. Questo è ad esempio il caso di parametri sintonizzabili come BORDER_WIDTH = 2
o TIMEOUT = 60; // seconds
o modelli come API_ENDPOINT = "https://api.example.com/v2/"
- anche se probabilmente alcuni o tutti dovrebbero essere specificati nei file di configurazione piuttosto che nel codice.