I having a problem in my switch/case statement. The error says : "Case expressions must be constant expressions". I understand the error and I can resolve it using If but can someone tells me why the case expression must be constant in a switch/case. A code example of my error :
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 for your explanation !!
The switch case in Java works like an if-else ladder, i.e., multiple conditions can be checked at once. Switch is provided with an expression that can be a constant or literal expression that can be evaluated. The value of the expression is matched with each test case till a match is found.
The constant-expression for a case must be the same data type as the variable in the switch, and it must be a constant or a literal. When the variable being switched on is equal to a case, the statements following that case will execute until a break statement is reached.
A constant expression is an expression that yields a primitive type or a String, and whose value can be evaluated at compile time to a literal. The expression must evaluate without throwing an exception, and it must be composed of only the following: Primitive and String literals.
A switch works with the byte , short , char , and int primitive data types. It also works with enumerated types (discussed in Enum Types), the String class, and a few special classes that wrap certain primitive types: Character , Byte , Short , and Integer (discussed in Numbers and Strings).
So it can be evaluated during the compilation phase ( statically check )
See: http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.11 for a formal definition of the switch
.
Additionally it may help you to understand better how that switch
is transformed into bytecode:
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; } } }
And after compiling:
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 }
See that line marked as 1:
1: lookupswitch{ //2 1: 28; 9: 39; default: 50 }
It evaluates the value and goes to some other line. For instance if value is 9
it will jump to instruction 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
Which in turn jumps to instruction 58 :
58: return
All this wouldn't be possible if it was evaluated dynamically. That's why.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With