Comprendo che il compilatore ha bisogno che l'espressione sia nota al momento della compilazione per compilare uno switch, ma perché Foo.BA_ non è costante?
Sebbene siano costanti dal punto di vista di qualsiasi codice che viene eseguito dopo l'inizializzazione dei campi, non sono una costante di tempo di compilazione nel senso richiesto da JLS; vedi §15.28 espressioni costanti per la specifica di una costante espressione 1 . Questo si riferisce al §4.12.4 Variabili finali che definisce una "variabile costante" come segue:
Chiamiamo una variabile, di tipo primitivo o tipo String, che è finale e inizializzata con un'espressione costante in fase di compilazione (§15.28) una variabile costante. Il fatto che una variabile sia una variabile costante o meno può avere implicazioni rispetto all'inizializzazione della classe (§12.4.1), compatibilità binaria (§13.1, §13.4.9) e assegnazione definita (§16).
Nel tuo esempio, le variabili Foo.BA * non hanno inizializzatori e quindi non si qualificano come "variabili costanti". La correzione è semplice; modificare le dichiarazioni delle variabili Foo.BA * in modo che abbiano inizializzatori che sono espressioni costanti in fase di compilazione.
In altri esempi (in cui gli inizializzatori sono già espressioni costanti in fase di compilazione), dichiarando la variabile come final
potrebbe essere ciò che è necessario.
È possibile modificare il codice per utilizzare una enum
anziché una int
costante, ma ciò comporta un altro paio di restrizioni diverse:
1 - Le restrizioni di espressione costante possono essere riassunte come segue. Espressioni costanti a) possono utilizzare tipi primitivi e String
solo, b) consentire primarie che sono letterali (a parte null
) e variabili costanti solo, c) consentire espressioni costanti eventualmente parentesi, come sottoespressioni, d) consentire agli operatori tranne per operatori di assegnazione, ++
, --
o instanceof
, e e) consentire il cast di tipi String
solo a tipi primitivi .
Si noti che questo non include alcuna forma di chiamate di metodo o di lambda, new
, .class
. .length
o sottoscrizione di array. Inoltre, qualsiasi uso di valori di array, enum
valori, valori di tipi di wrapper primitivi, boxe e unboxing sono tutti esclusi a causa di a).