所以,我正在研究这个有一些静态常量的类:
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 required3 个案例标签中的每一个都出现错误。
constant expression required
我知道编译器需要在编译时知道表达式才能编译开关,但为什么不是Foo.BA_常量?
Foo.BA_
我知道编译器需要在编译时知道表达式才能编译开关,但为什么 Foo.BA_ 不是常量?
虽然从在字段初始化后执行的任何代码的角度来看它们是恒定的,但它们不是 JLS 要求的 编译时间常数 ; 有关常量表达式 1的规范,请参见拥抱 15.28 常量表达式。这指的是拥抱4.12.4 最终变量,它定义了一个“常量变量”,如下所示: __
我们将原始类型或字符串类型的变量称为最终变量,并使用编译时常量表达式(拥抱15.28)进行初始化,称为常量变量。变量是否为常量变量可能对类初始化(搂12.4.1)、二进制兼容性(搂13.1、搂13.4.9)和明确赋值(搂16)有影响。
在您的示例中, Foo.BA 变量没有初始化程序,因此不符合“常量变量”的条件。修复很简单;将 Foo.BA 变量声明更改为具有编译时常量表达式的初始化程序。
在其他示例中(初始化程序已经是编译时常量表达式),将变量声明为final可能是需要的。
final
您可以更改代码以使用 anenum而不是int常量,但这会带来另外几个不同的限制:
enum
int
default
case
1 - 常量表达式的限制可以总结如下。常量表达式 a) 只能使用原始类型String,b) 只允许作为字面量的基本类型(除了null)和常量变量,c) 允许可能用括号括起来作为子表达式的常量表达式,d) 允许除赋值运算符之外的运算符,++,--或instanceof, 和e) 允许或String仅允许类型转换为原始类型。
String
null
++
--
instanceof
请注意,这不包括任何形式的方法或 lambda 调用、new、.class。.length或数组下标。此外,由于 a),任何使用数组值、enum值、原始包装类型的值、装箱和拆箱都被排除在外。
new
.class
.length