Java switch 语句:需要常量表达式,但它是常量 [英] Java switch statement: Constant expression required, but it IS constant
问题描述
所以,我正在研究这个有一些静态常量的类:
So, I am working on this class that has a few static constants:
public abstract class Foo {
...
public static final int BAR;
public static final int BAZ;
public static final int BAM;
...
}
然后,我想要一种基于常量获取相关字符串的方法:
Then, I would like a way to get a relevant string based on the constant:
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";
}
}
但是,当我编译时,在 3 个 case 标签中的每一个标签上都会出现 constant expression required
错误.
However, when I compile, I get a constant expression required
error on each of the 3 case labels.
我知道编译器需要在编译时知道表达式才能编译开关,但为什么 Foo.BA_
不是常量?
I understand that the compiler needs the expression to be known at compile time to compile a switch, but why isn't Foo.BA_
constant?
推荐答案
我知道编译器需要在编译时知道表达式才能编译开关,但为什么 Foo.BA_ 不是常量?
I understand that the compiler needs the expression to be known at compile time to compile a switch, but why isn't Foo.BA_ constant?
虽然从字段初始化后执行的任何代码的角度来看,它们都是常量,但它们不是 JLS 要求的编译时常量;参见 §15.28 常量表达式用于常量表达式1的规范.这是指§4.12.4 最终变量它定义了一个常量变量",如下所示:
While they are constant from the perspective of any code that executes after the fields have been initialized, they are not a compile time constant in the sense required by the JLS; see §15.28 Constant Expressions for the specification of a constant expression1. This refers to §4.12.4 Final Variables which defines a "constant variable" as follows:
我们将原始类型或字符串类型的变量称为常量变量,该变量是最终的并使用编译时常量表达式(第 15.28 节)进行初始化.变量是否为常量变量可能会影响类初始化(第 12.4.1 节)、二进制兼容性(第 13.1 节、第 13.4.9 节)和明确赋值(第 16 节).
We call a variable, of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28) a constant variable. Whether a variable is a constant variable or not may have implications with respect to class initialization (§12.4.1), binary compatibility (§13.1, §13.4.9) and definite assignment (§16).
在您的示例中, Foo.BA* 变量没有初始值设定项,因此不符合常量变量"的要求.修复很简单;将 Foo.BA* 变量声明更改为具有编译时常量表达式的初始值设定项.
In your example, the Foo.BA* variables do not have initializers, and hence do not qualify as "constant variables". The fix is simple; change the Foo.BA* variable declarations to have initializers that are compile-time constant expressions.
在其他示例中(其中初始化程序已经是编译时常量表达式),可能需要将变量声明为 final
.
In other examples (where the initializers are already compile-time constant expressions), declaring the variable as final
may be what is needed.
您可以更改代码以使用 enum
而不是 int
常量,但这会带来另外几个不同的限制:
You could change your code to use an enum
rather than int
constants, but that brings another couple of different restrictions:
- 你必须包括一个
default
case,即使你对enum
的每个已知值都有case
;见 为什么枚举上的开关是否需要默认值? case
标签必须都是显式的enum
值,而不是计算结果为enum
值的表达式.
- You must include a
default
case, even if you havecase
for every known value of theenum
; see Why is default required for a switch on an enum? - The
case
labels must all be explicitenum
values, not expressions that evaluate toenum
values.
1 - 常量表达式限制可以总结如下.常量表达式 a) 只能使用原始类型和 String
,b) 允许主要是文字(除了 null
)和常量变量,c) 允许常量表达式可能括起来作为子表达式,d) 允许除赋值运算符之外的运算符,++
、--
或 instanceof
,以及 e) 允许类型转换为原始类型或仅 String
.
1 - The constant expression restrictions can be summarized as follows. Constant expressions a) can use primitive types and String
only, b) allow primaries that are literals (apart from null
) and constant variables only, c) allow constant expressions possibly parenthesised as subexpressions, d) allow operators except for assignment operators, ++
, --
or instanceof
, and e) allow type casts to primitive types or String
only.
请注意,这不包括任何形式的方法或 lambda 调用、new
、.class
..length
或数组下标.此外,任何使用数组值、enum
值、原始包装类型的值、装箱和拆箱都被排除在外,因为 a).
Note that this doesn't include any form of method or lambda calls, new
, .class
. .length
or array subscripting. Furthermore, any use of array values, enum
values, values of primitive wrapper types, boxing and unboxing are all excluded because of a).
这篇关于Java switch 语句:需要常量表达式,但它是常量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!