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";
}
}
但是,当我编译时,我得到一个需要的常量表达式 3 个案例标签均出现错误。
我知道编译器需要在编译时知道表达式才能编译开关,但为什么 Foo.BA_ 不是常量?
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";
}
}
However, when I compile, I get a constant expression required
error on each of the 3 case labels.
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
虽然从字段初始化后执行的任何代码的角度来看它们都是常量,但它们不是 JLS 所要求的意义上的编译时常量;请参阅§15.28 常量表达式用于指定常量表达式1。这是指§4.12.4 最终变量它定义了一个“常量变量”,如下所示:
在您的示例中, Foo.BA* 变量没有初始值设定项,因此不符合“常量变量”的资格。修复方法很简单;更改 Foo.BA* 变量声明,使其具有作为编译时常量表达式的初始值设定项。
在其他示例中(其中初始值设定项已经是编译时常量表达式),可能需要将变量声明为
final
。您可以更改代码以使用
enum
而不是int
常量,但这会带来另外几个不同的限制:default
大小写,即使您对enum
的每个已知值都有case
;请参阅 为什么枚举上的开关是否需要默认值?case
标签必须全部是显式enum
值,而不是计算结果为enum
的表达式> 价值观。1 - 常量表达式限制可总结如下。常量表达式 a) 只能使用基元类型和
String
,b) 只允许文字类型(null
除外)和常量变量,c) 允许可能带括号的常量表达式作为子表达式,d) 允许除赋值运算符、++
、--
或instanceof
之外的运算符,并且 e) 允许类型转换为原始类型或仅String
。请注意,这不包括任何形式的方法或 lambda 调用、
new
、.class
。.length
或数组下标。此外,由于 a),任何数组值、枚举值、原始包装类型值、装箱和拆箱的使用都被排除。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:
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.
In other examples (where the initializers are already compile-time constant expressions), declaring the variable as
final
may be what is needed.You could change your code to use an
enum
rather thanint
constants, but that brings another couple of different restrictions:default
case, even if you havecase
for every known value of theenum
; see Why is default required for a switch on an enum?case
labels must all be explicitenum
values, not expressions that evaluate toenum
values.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 fromnull
) and constant variables only, c) allow constant expressions possibly parenthesised as subexpressions, d) allow operators except for assignment operators,++
,--
orinstanceof
, and e) allow type casts to primitive types orString
only.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).您得到需要常量表达式,因为您将值从常量中遗漏了。尝试:
You get Constant expression required because you left the values off your constants. Try:
我在 Android 上遇到了这个错误,我的解决方案就是使用:
而不是
I got this error on Android, and my solution was just to use:
instead of
因为这些不是编译时间常数。考虑以下有效代码:
您只能在运行时知道
BAR
的值。Because those are not compile time constants. Consider the following valid code:
You can only know the value of
BAR
in runtime.您可以使用枚举,如下例所示:
来源:
带有枚举的 Switch 语句
You can use an enum like in this example:
Source:
Switch statement with enum
我建议使用以下方式:
I recommend using the following way:
这是很久以前就回答过的问题,可能不相关,但以防万一。
当我遇到这个问题时,我只是使用了
if
语句而不是switch
,它就解决了错误。这当然是一种解决方法,可能不是“正确”的解决方案,但就我而言,这已经足够了。
编辑:2021.01.21
这个答案有点误导,我想澄清一下。
if
替换switch
语句不应被视为 goto 解决方案,有充分的理由解释为什么switch
和这两个概念>如果
存在于软件开发中,以及在两者之间进行选择时要考虑的性能问题。在我的具体情况下,使用
if
语句足以解决问题。开发人员应该花时间来决定这是否是解决您当前遇到的问题的正确解决方案。因此,这个答案应该仅被视为我在第一个回复中所述的特定情况下的解决方法,而绝不是这个问题的正确答案
This was answered ages ago and probably not relevant, but just in case.
When I was confronted with this issue, I simply used an
if
statement instead ofswitch
, it solved the error.It is of course a workaround and probably not the "right" solution, but in my case it was just enough.
Edit: 2021.01.21
This Answer is a bit misleading, And I would like to clarify it.
switch
statement with anif
should not be considered as a goto solution, there are very good reasons why both concepts ofswitch
andif
exist in software development, as well as performance matters to consider when choosing between the two.In my specific case, using an
if
statement instead was just enough to solve the problem. Developers should take the time and decide if this is the right solution for the current problem you have at hand.Thus this answer should be considered solely as a workaround in specific cases as stated in my first response, and by no means as the correct answer to this question
如果您在开关盒中使用它,那么您需要在将该值插入开关之前获取枚举的类型。例如 :
枚举就像:
If you're using it in a switch case then you need to get the type of the enum even before you plug that value in the switch. For instance :
And the enum is like:
有时开关变量也会犯这个错误,例如:
要解决这个问题,您应该将变量转换为int(在本例中)。所以:
Sometimes the switch variable can also make that error for example:
To solve you should cast the variable to int(in this case). So:
就我而言,我得到了这个异常,因为
在第二种情况下,我从实例
var.MODIFICAR_KM:
调用常量,但我应该直接从班级。In my case, I was getting this exception because
in the second case I was calling the constant from the instance
var.MODIFICAR_KM:
but I should useVariablesKmDialog.OBTENER_KM
directly from the class.下面的代码是不言自明的,
我们可以使用带有 switch case 的枚举:
基于可以映射枚举中的类值:
希望它有帮助:)
Below code is self-explanatory,
We can use an enum with a switch case:
Based on the class values from the enum can be mapped:
Hope it helps :)
在 Android 中执行以下操作时出现此错误:
尽管声明了一个常量:
public static Final String ADMIN_CONSTANT= "Admin";
我通过将代码更改为以下内容解决了该问题:
Got this error in Android while doing something like this:
despite declaring a constant:
public static final String ADMIN_CONSTANT= "Admin";
I resolved the issue by changing my code to this:
问题在于 int 和 Integer (我不知道为什么),将 int 更改为 string 并且它可以工作
The problem is with the int and Integer (i do not why), change the int to string and it work's
只需在“geadle.properties”中添加“android.nonFinalResIds=false”
,所有“需要常量表达式”错误就会消失。
Just add "android.nonFinalResIds=false"
In 'geadle.properties' and all 'Constant expression required' bugs will be gone.
我建议您使用枚举:)
看看这个:
然后您可以像这样使用它:
I recommend you to use enums :)
Check this out:
Then you can use it like this: