Я понимаю, что для компиляции переключателя необходимо, чтобы выражение было известно во время компиляции, но почему Foo.BA_ не является константой?
Хотя они постоянны с точки зрения любого кода, который выполняется после инициализации полей, они не являются постоянной времени компиляции в смысле, требуемом JLS; см. §15.28 Выражения констант для спецификации выражения констант 1 . Это относится к §4.12.4 Окончательные переменные , которые определяют «постоянную переменную» следующим образом:
Мы называем переменную примитивного типа или типа String, которая является конечной и инициализируется константным выражением времени компиляции (§15.28) постоянной переменной. Независимо от того, является ли переменная постоянной или нет, это может иметь значение в отношении инициализации класса (§12.4.1), двоичной совместимости (§13.1, §13.4.9) и определенного присваивания (§16).
В вашем примере переменные Foo.BA * не имеют инициализаторов и, следовательно, не квалифицируются как «постоянные переменные». Исправление просто; измените объявления переменных Foo.BA *, чтобы инициализаторы были константными выражениями во время компиляции.
В других примерах (где инициализаторы уже являются константными выражениями времени компиляции), объявление переменной как final
может быть тем, что необходимо.
Вы можете изменить свой код, чтобы использовать enum
вместо int
констант, но это приносит еще пару различных ограничений:
1 - Ограничения константных выражений можно суммировать следующим образом. Выражения констант a) могут использовать типы примитивов и только String
, b) разрешать основные цвета, которые являются литералами (кроме null
) и только константными переменными, c) разрешать выражения констант, возможно заключенные в скобки как подвыражения, d) разрешать операторы за исключением присваивания операторы ++
, --
или instanceof
и e) разрешают приведение типов к примитивным типам или только String
.
Обратите внимание, что это не включает в себя какие-либо методы или лямбда-вызовы, new
, .class
. .length
или массив подписки. Кроме того, любое использование значений массива, enum
значений, значений типов примитивных оболочек, упаковки и распаковки исключено из-за a).