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