Java switch 语句:需要常量表达式,但它是常量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3827393/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java switch statement: Constant expression required, but it IS constant
提问by Austin Hyde
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.
但是,当我编译时,我constant expression required
在 3 个案例标签中的每一个标签上都会出现错误。
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_
常量?
采纳答案by Stephen C
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_ 不是常量?
While they are constant from the perspective of any code that executes after the fields have been initialized, they are not a compile time constantin the sense required by the JLS; see §15.28 Constant Expressionsfor the specification of a constant expression1. This refers to §4.12.4 Final Variableswhich defines a "constant variable" as follows:
虽然从字段初始化后执行的任何代码的角度来看,它们都是常量,但它们不是JLS 要求的编译时常量;有关常量表达式1的规范,请参阅§15.28 常量表达式。这指的是§4.12.4 Final Variables,它定义了一个“常量变量”,如下所示:
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).
我们将原始类型或字符串类型的变量称为常量变量,该变量是最终的并使用编译时常量表达式(第 15.28 节)进行初始化。变量是否为常量变量可能会影响类初始化(第 12.4.1 节)、二进制兼容性(第 13.1 节、第 13.4.9 节)和明确赋值(第 16 节)。
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.
在您的示例中, Foo.BA* 变量没有初始值设定项,因此不符合“常量变量”的条件。修复很简单;将 Foo.BA* 变量声明更改为具有编译时常量表达式的初始值设定项。
In other examples (where the initializers are already compile-time constant expressions), declaring the variable as final
may be what is needed.
在其他示例中(其中初始化程序已经是编译时常量表达式),final
根据需要声明变量。
You could change your code to use an enum
rather than int
constants, but that brings another couple of different restrictions:
您可以更改代码以使用 anenum
而不是int
常量,但这会带来另外几个不同的限制:
- You mustinclude 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.
- 您必须包含一个
default
案例,即使您拥有case
; 的每个已知值enum
。请参阅为什么枚举上的开关需要默认值? - 该
case
标签都必须明确的enum
值,而不是计算结果为表达式的enum
值。
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.
1 - 常量表达式限制可以总结如下。常量表达式 a) 只能使用基本类型String
,b) 只允许作为文字的主要类型(除了null
)和常量变量,c) 允许常量表达式可能被括号作为子表达式,d) 允许除赋值运算符之外的运算符,++
,--
or instanceof
,和e) 允许类型转换为原始类型或String
仅允许类型转换。
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).
请注意,这不包括任何形式的方法或 lambda 调用、new
、.class
。.length
或数组下标。此外,enum
由于 a) ,任何对数组值、值、原始包装类型的值、装箱和拆箱的使用都被排除在外。
回答by Sheldon L. Cooper
Because those are not compile time constants. Consider the following valid code:
因为那些不是编译时常量。考虑以下有效代码:
public static final int BAR = new Random().nextInt();
You can only know the value of BAR
in runtime.
你只能知道BAR
在运行时的值。
回答by Tony Ennis
You get Constant expression requiredbecause you left the values off your constants. Try:
您需要常量表达式,因为您将值从常量中删除了。尝试:
public abstract class Foo {
...
public static final int BAR=0;
public static final int BAZ=1;
public static final int BAM=2;
...
}
回答by thenosic
You can use an enum like in this example:
您可以在本例中使用枚举:
public class MainClass {
enum Choice { Choice1, Choice2, Choice3 }
public static void main(String[] args) {
Choice ch = Choice.Choice1;
switch(ch) {
case Choice1:
System.out.println("Choice1 selected");
break;
case Choice2:
System.out.println("Choice2 selected");
break;
case Choice3:
System.out.println("Choice3 selected");
break;
}
}
}
Source: Switch statement with enum
来源: 带有枚举的 Switch 语句
回答by everton
I recommend you to use enums :)
我建议你使用枚举:)
Check this out:
看一下这个:
public enum Foo
{
BAR("bar"),
BAZ("baz"),
BAM("bam");
private final String description;
private Foo(String description)
{
this.description = description;
}
public String getDescription()
{
return description;
}
}
Then you can use it like this:
然后你可以像这样使用它:
System.out.println(Foo.BAR.getDescription());
回答by Teo Inke
I got this error on Android, and my solution was just to use:
我在 Android 上遇到了这个错误,我的解决方案就是使用:
public static final int TAKE_PICTURE = 1;
instead of
代替
public static int TAKE_PICTURE = 1;
回答by Samer Murad
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 of switch
, it solved the error.
It is of course a workaround and probably not the "right" solution, but in my case it was just enough.
这是很久以前回答的,可能不相关,但以防万一。当我遇到这个问题时,我只是使用了一个if
语句而不是switch
,它解决了错误。这当然是一种解决方法,可能不是“正确”的解决方案,但就我而言,这已经足够了。
回答by Mahdi-Malv
Sometimes the switch variablecan also make that error for example:
有时switch 变量也会导致该错误,例如:
switch(view.getTag()) {//which is an Object type
case 0://will give compiler error that says Constant expression required
//...
}
To solve you should cast the variable to int(in this case). So:
要解决此问题,您应该将变量强制转换为 int(在这种情况下)。所以:
switch((int)view.getTag()) {//will be int
case 0: //No Error
//...
}
回答by Ojonugwa Jude Ochalifu
Got this error in Android while doing something like this:
在执行以下操作时,在 Android 中出现此错误:
roleSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch (parent.getItemAtPosition(position)) {
case ADMIN_CONSTANT: //Threw the error
}
despite declaring a constant:
尽管声明了一个常量:
public static final String ADMIN_CONSTANT= "Admin";
public static final String ADMIN_CONSTANT= "Admin";
I resolved the issue by changing my code to this:
我通过将代码更改为以下解决了该问题:
roleSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selectedItem = String.valueOf(parent.getItemAtPosition(position));
switch (selectedItem) {
case ADMIN_CONSTANT:
}
回答by Gian Gomen
In my case, I was getting this exception because
就我而言,我收到此异常是因为
switch (tipoWebServ) {
case VariablesKmDialog.OBTENER_KM:
resultObtenerKm(result);
break;
case var.MODIFICAR_KM:
resultModificarKm(result);
break;
}
in the second case I was calling the constant from the instance var.MODIFICAR_KM:
but I should use VariablesKmDialog.OBTENER_KM
directly from the class.
在第二种情况下,我从实例调用常量,var.MODIFICAR_KM:
但我应该VariablesKmDialog.OBTENER_KM
直接从类中使用。