Вопрос-ответ

Java switch statement: Constant expression required, but it IS constant

Оператор Java switch: требуется постоянное выражение, но оно постоянное

Итак, я работаю над этим классом, который имеет несколько статических констант:

public abstract class Foo {
...
public static final int BAR;
public static final int BAZ;
public static final int BAM;
...
}

Тогда я хотел бы найти способ получить соответствующую строку на основе константы:

public static String lookup(int constant) {
switch (constant) {
case Foo.BAR: return "bar";
case Foo.BAZ: return "baz";
case Foo.BAM: return "bam";
default: return "unknown";
}
}

Однако при компиляции я получаю constant expression required ошибку для каждой из 3 меток case.

Я понимаю, что компилятору нужно, чтобы выражение было известно во время компиляции для компиляции switch, но почему оно не является Foo.BA_ постоянным?

Переведено автоматически
Ответ 1

Я понимаю, что компилятору нужно, чтобы выражение было известно во время компиляции для компиляции switch, но почему 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 только, null б) разрешают только первичные значения, которые являются литералами (кроме ++) и постоянными переменными, в) разрешают константные выражения, возможно, заключенные в скобки как подвыражения, d) разрешают операторы, за исключением операторов присваивания, --, instanceof или String, и e) разрешают приведение типов только к примитивным типам или,,,.

Обратите внимание, что это не включает в себя какую-либо форму метода или лямбда-вызовов, new, .class. .length или подписку на массив. Кроме того, любое использование значений массива, enum значений, значений примитивных типов-оболочек, упаковка и распаковка - все это исключается из-за a).

Ответ 2

Вы получаете требуется постоянное выражение, потому что вы оставили значения в своих константах. Попробуйте:

public abstract class Foo {
...
public static final int BAR=0;
public static final int BAZ=1;
public static final int BAM=2;
...
}
Ответ 3

Я получил эту ошибку на Android, и моим решением было просто использовать:

public static final int TAKE_PICTURE = 1;

вместо

public static int TAKE_PICTURE = 1;
Ответ 4

Потому что это не константы времени компиляции. Рассмотрим следующий допустимый код:

public static final int BAR = new Random().nextInt();

Вы можете узнать значение BAR только во время выполнения.

java