Ich verstehe, dass der Compiler den Ausdruck zur Kompilierungszeit kennen muss, um einen Switch zu kompilieren, aber warum ist Foo.BA_ nicht konstant?
Während sie aus der Sicht eines Codes konstant sind, der nach der Initialisierung der Felder ausgeführt wird, sind sie keine Kompilierungszeitkonstante im Sinne des JLS. siehe §15.28 Konstante Ausdrücke für die Angabe eines konstanten Ausdrucks 1 . Dies bezieht sich auf §4.12.4 Endvariablen, der eine "konstante Variable" wie folgt definiert:
Wir nennen eine Variable vom primitiven Typ oder Typ String, die endgültig ist und mit einem konstanten Ausdruck zur Kompilierungszeit (§15.28) initialisiert wird, eine konstante Variable. Ob eine Variable eine konstante Variable ist oder nicht, kann Auswirkungen auf die Klasseninitialisierung (§12.4.1), die Binärkompatibilität (§13.1, §13.4.9) und die definitive Zuordnung (§16) haben.
In Ihrem Beispiel haben die Foo.BA * -Variablen keine Initialisierer und gelten daher nicht als "konstante Variablen". Das Update ist einfach; Ändern Sie die Foo.BA * -Variablendeklarationen so, dass Initialisierer Konstantenausdrücke zur Kompilierungszeit sind.
In anderen Beispielen (in denen die Initialisierer bereits Konstantenausdrücke zur Kompilierungszeit sind) wird die Variable als final
erforderlich deklariert .
Sie könnten Ihren Code so ändern, dass er eine Konstante enum
anstelle von int
Konstanten verwendet. Dies bringt jedoch noch einige andere Einschränkungen mit sich:
1 - Die Einschränkungen für konstante Ausdrücke können wie folgt zusammengefasst werden. Konstante Ausdrücke a) können primitive Typen verwenden und String
nur, b) Primäre zulassen, die Literale (außer null
) und nur konstante Variablen sind, c) konstante Ausdrücke zulassen, die möglicherweise als Unterausdrücke in Klammern stehen, d) Operatoren außer Zuweisungsoperatoren zulassen ++
, --
oder instanceof
, und e) Typumwandlungen für primitive Typen oder String
nur zulassen .
Beachten Sie, dass dies keine Form von Verfahren oder Lambda - Anrufe enthält, new
, .class
. .length
oder Array-Subskription. Darüber hinaus ist die Verwendung von Array-Werten, enum
Werten, Werten primitiver Wrapper-Typen, Boxing und Unboxing aufgrund von a) ausgeschlossen.