2011-01-20 73 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语言中工作。

相关问题