2011-01-20 76 views
26

我的switch/case語句有問題。錯誤說:「Case表達式必須是常量表達式」。我理解錯誤,我可以使用If來解決它,但是有人可以告訴我爲什麼case/case中的case表達式必須是常量。 我的錯誤的代碼示例:一個開關Java問題:case表達式必須是常量表達式

public boolean onOptionsItemSelected(MenuItem item) { 
    int idDirectory = ((MenuItem) findViewById(R.id.createDirectory)).getItemId(); 
    int idSuppression = ((MenuItem) findViewById(R.id.recycleTrash)).getItemId(); 
    int idSeeTrash = ((MenuItem) findViewById(R.id.seeTrash)).getItemId(); 

    switch (item.getItemId()) { 
    case idDirectory: 
     createDirectory(currentDirectory); 
     break; 
    case idSuppression: 
     recycleTrash(); 
     break; 
    case idSeeTrash: 
     seeTrash(); 
     break; 
    } 

    return super.onOptionsItemSelected(item); 
} 

Thx爲您的解釋!

+5

?如果您已經擁有該ID,則無需獲取該項目即可獲取該ID! – 2011-01-20 01:39:32

+2

開關語句是一種難聞的氣味......我建議您考慮使用多態性或適配器模式,以獲得更好看的代碼。此外,你可以完全避免這些問題。 – Bnjmn 2011-01-20 02:13:08

+0

@Bnjmn我同意,特別是當病情經常重複時。如果你使用它很少它可能是好的。另外,我有時使用多態來創建初始具體實例。 – OscarRyz 2011-01-20 02:32:53

回答

54

因此,它可以在編譯期進行評估(靜態檢查)

請參見:http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11switch的正式定義。

此外,它可以幫助你更好地瞭解怎麼說switch被轉換成字節碼:

class Switch { 
    void x(int n) { 
    switch(n) { 
     case 1: System.out.println("one"); break; 
     case 9: System.out.println("nine"); break; 
     default: System.out.println("nothing"); break; 
    } 
    } 
} 

和編譯後:

C:\>javap -c Switch 
Compiled from "Switch.java" 
class Switch extends java.lang.Object{ 
Switch(); 
    Code: 
    0: aload_0 
    1: invokespecial #1; //Method java/lang/Object."<init>":()V 
    4: return 

void x(int); 
    Code: 
    0: iload_1 
    1: lookupswitch{ //2 
       1: 28; 
       9: 39; 
       default: 50 } 
    28: getstatic  #2; //Field java/lang/System.out:Ljava/io/PrintStream; 
    31: ldc  #3; //String one 
    33: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    36: goto 58 
    39: getstatic  #2; //Field java/lang/System.out:Ljava/io/PrintStream; 
    42: ldc  #5; //String nine 
    44: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    47: goto 58 
    50: getstatic  #2; //Field java/lang/System.out:Ljava/io/PrintStream; 
    53: ldc  #6; //String nothing 
    55: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    58: return 

} 

見該行標記爲1:

1: lookupswitch{ //2 
      1: 28; 
      9: 39; 
      default: 50 } 

它評估的價值和去som另一條線。例如,如果值是9它會跳到指令39:

39: getstatic  #2; //Field java/lang/System.out:Ljava/io/PrintStream; 
    42: ldc  #5; //String nine 
    44: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 
    47: goto 58 

這反過來又跳到指令58:

58: return 

如果它是動態評估所有這一切都將是不可能的。這就是爲什麼。

3

idDirectory和其他需要是一個常量,而不是一個聲明的變量。 Switch在這種情況下將不起作用,您需要切換到if-else構造。

編輯我明白了OP的含義。這就是開關如何在java語言中工作。

相關問題