[英]Java switch statement: Constant expression required, but it IS constant
所以,我正在研究這個有一些靜態常量的類:
public abstract class Foo {
...
public static final int BAR;
public static final int BAZ;
public static final int BAM;
...
}
我知道編譯器需要在編譯時知道表達式才能編譯開關,但為什么 Foo.BA_ 不是常量?
雖然從初始化字段后執行的任何代碼的角度來看,它們是常量,但它們不是 JLS 要求的編譯時間常量; 有關常量表達式1的規范,請參見第 15.28 節常量表達式。 這指的是§4.12.4 最終變量,它定義了一個“常量變量”,如下所示:
我們將原始類型或 String 類型的變量稱為 final 並使用編譯時常量表達式(第 15.28 節)初始化的變量為常量變量。 變量是否為常量變量可能對類初始化(§12.4.1)、二進制兼容性(§13.1、§13.4.9)和明確賦值(§16)有影響。
在您的示例中, 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),任何使用數組值、 enum
值、原始包裝類型的值、裝箱和拆箱都被排除在外。
您需要常量表達式,因為您將值從常量中刪除。 嘗試:
public abstract class Foo {
...
public static final int BAR=0;
public static final int BAZ=1;
public static final int BAM=2;
...
}
我在 Android 上遇到了這個錯誤,我的解決方案就是使用:
public static final int TAKE_PICTURE = 1;
代替
public static int TAKE_PICTURE = 1;
因為那些不是編譯時常量。 考慮以下有效代碼:
public static final int BAR = new Random().nextInt();
您可以像本例中那樣使用枚舉:
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;
}
}
}
我建議使用以下方式:
public enum Animal {
DOG("dog"), TIGER("tiger"), LION("lion");
private final String name;
@Override
public String toString() {
return this.name;
}
}
public class DemoSwitchUsage {
private String getAnimal(String name) {
Animal animalName = Animal.valueOf(name);
switch(animalName) {
case DOG:
// write the code required.
break;
case LION:
// Write the code required.
break;
default:
break;
}
}
}
這是很久以前回答的,可能不相關,但以防萬一。 當我遇到這個問題時,我只是使用
if<\/code>語句而不是
switch<\/code> ,它解決了錯誤。
這當然是一種解決方法,可能不是“正確”的解決方案,但就我而言,這已經足夠了。
這個答案有點誤導,我想澄清一下。
用if<\/code>替換switch<\/code>語句不應該被視為 goto 解決方案,有很好的理由說明switch<\/code>和if<\/code>的概念存在於軟件開發中,以及在兩者之間進行選擇時要考慮的性能問題。
<\/li>
在我的具體情況下,使用
if<\/code>語句就足以解決問題。
開發人員應該花時間決定這是否是您手頭當前問題的正確解決方案。
因此,如我在第一個回復中所述,此答案應僅被視為特定情況下的解決方法,而絕不是此問題的正確答案
如果您在開關盒中使用它,那么您需要在將該值插入開關之前獲取枚舉的類型。 例如 :
SomeEnum someEnum = SomeEnum.values()[1];
枚舉就像:
就我而言,我得到了這個例外,因為
switch (tipoWebServ) {
case VariablesKmDialog.OBTENER_KM:
resultObtenerKm(result);
break;
case var.MODIFICAR_KM:
resultModificarKm(result);
break;
}
在第二種情況下,我從實例var.MODIFICAR_KM:
但我應該直接從類中使用VariablesKmDialog.OBTENER_KM
。
下面的代碼是不言自明的,我們可以使用帶有開關盒的枚舉:
/**
*
*/
enum ClassNames {
STRING(String.class, String.class.getSimpleName()),
BOOLEAN(Boolean.class, Boolean.class.getSimpleName()),
INTEGER(Integer.class, Integer.class.getSimpleName()),
LONG(Long.class, Long.class.getSimpleName());
private Class typeName;
private String simpleName;
ClassNames(Class typeName, String simpleName){
this.typeName = typeName;
this.simpleName = simpleName;
}
}
有時switch 變量也會導致該錯誤,例如:
switch(view.getTag()) {//which is an Object type
case 0://will give compiler error that says Constant expression required
//...
}
要解決,您應該將變量轉換為 int(在這種情況下)。 所以:
switch((int)view.getTag()) {//will be int
case 0: //No Error
//...
}
在執行以下操作時在 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
}
問題在於 int 和 Integer(我不知道為什么),將 int 更改為 string 並且它可以工作
public abstract class Foo {
...
public static final String BAR;
public static final String BAZ;
public static final String BAM;
...
}
public static String lookup(String constant) {
switch (constant) {
case Foo.BAR: return "bar";
case Foo.BAZ: return "baz";
case Foo.BAM: return "bam";
default: return "unknown";
}
}
我建議你使用枚舉:)
看一下這個:
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;
}
}
然后你可以像這樣使用它:
System.out.println(Foo.BAR.getDescription());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.