Je comprends que le compilateur a besoin que l'expression soit connue au moment de la compilation pour compiler un commutateur, mais pourquoi Foo.BA_ n'est-il pas constant?
Bien qu'ils soient constants du point de vue de tout code qui s'exécute après que les champs ont été initialisés, ils ne sont pas une constante de temps de compilation au sens requis par le JLS; voir §15.28 Expressions constantes pour la spécification d'une expression constante 1 . Ceci fait référence au §4.12.4 Variables finales qui définit une "variable constante" comme suit:
Nous appelons une variable, de type primitif ou de type String, qui est finale et initialisée avec une expression constante à la compilation (§15.28) une variable constante. Le fait qu'une variable soit une variable constante ou non peut avoir des implications en ce qui concerne l'initialisation de classe (§12.4.1), la compatibilité binaire (§13.1, §13.4.9) et l'affectation définie (§16).
Dans votre exemple, les variables Foo.BA * n'ont pas d'initialiseurs et ne sont donc pas qualifiées de "variables constantes". Le correctif est simple; changez les déclarations de variable Foo.BA * pour avoir des initialiseurs qui sont des expressions constantes à la compilation.
Dans d'autres exemples (où les initialiseurs sont déjà des expressions constantes au moment de la compilation), déclarer la variable selon les final
besoins.
Vous pouvez modifier votre code pour utiliser un enum
plutôt que des int
constantes, mais cela apporte un autre couple de restrictions différentes:
1 - Les restrictions d'expression constante peuvent être résumées comme suit. Les expressions constantes a) peuvent utiliser des types primitifs et String
seulement, b) autoriser les primaires qui sont des littéraux (en dehors de null
) et des variables constantes uniquement, c) autoriser les expressions constantes éventuellement entre parenthèses comme des sous-expressions, d) autoriser les opérateurs sauf pour les opérateurs d'affectation ++
, --
ou instanceof
, et e) autoriser les transtypages de types en types primitifs ou String
uniquement.
Notez que cela ne comprend aucune forme d'appels de méthode ou lambda, new
, .class
. .length
ou indice de tableau. En outre, toute utilisation de valeurs de tableau, de enum
valeurs, de valeurs de types d'encapsuleurs primitifs, de mise en boîte et de déballage sont toutes exclues en raison de a).