The switch
statement transfers control to one of several statements depending on
the value of an expression.
SwitchStatement:
switch (
Expression)
SwitchBlock SwitchBlock:
{
SwitchBlockStatementGroupsoptSwitchLabelsopt
}
SwitchBlockStatementGroups:
SwitchBlockStatementGroup
SwitchBlockStatementGroups
SwitchBlockStatementGroup SwitchBlockStatementGroup:
SwitchLabelsBlockStatements SwitchLabels:
SwitchLabel
SwitchLabelsSwitchLabel SwitchLabel:
case
ConstantExpression:
default :
The type of the Expression must be char
, byte
, short
, or int
, or a compile-time error occurs.
The body of a switch
statement must be a block. Any statement immediately contained by the block may be labeled with one or more case
or default
labels. These labels are said to be associated with the switch
statement, as are the values of the constant expressions (§15.27) in the case
labels.
All of the following must be true, or a compile-time error will result:
case
constant expression associated with a switch
statement must be assignable (§5.2) to the type of the switch
Expression.
case
constant expressions associated with a switch
statement may have the same value.
default
label may be associated with the same switch
statement.
In C and C++ the body of a switch
statement can be a statement and statements with case
labels do not have to be immediately contained by that statement. Consider the simple loop:
for (i = 0; i < n; ++i) foo();
where n
is known to be positive. A trick known as Duff's device can be used in C
or C++ to unroll the loop, but this is not valid Java code:
int q = (n+7)/8; switch (n%8) { case 0: do { foo(); // Great C hack, Tom, case 7: foo(); // but it's not valid in Java. case 6: foo(); case 5: foo(); case 4: foo(); case 3: foo(); case 2: foo(); case 1: foo(); } while (--q >= 0); }
Fortunately, this trick does not seem to be widely known or used. Moreover, it is less needed nowadays; this sort of code transformation is properly in the province of state-of-the-art optimizing compilers.
When the switch
statement is executed, first the Expression is evaluated. If evaluation of the Expression completes abruptly for some reason, the switch
statement completes abruptly for the same reason. Otherwise, execution continues by comparing the value of the Expression with each case
constant. Then there is a choice:
case
constants is equal to the value of the expression, then we say that the case
matches, and all statements after the matching case
label in the switch block, if any, are executed in sequence. If all these statements complete normally, or if there are no statements after the matching case
label, then the entire switch
statement completes normally.
case
matches but there is a default
label, then all statements after the matching default
label in the switch block, if any, are executed in sequence. If all these statements complete normally, or if there are no statements after the default
label, then the entire switch
statement completes normally.
case
matches and there is no default
label, then no further action is taken and the switch
statement completes normally.
If any statement immediately contained by the Block body of the switch
statement completes abruptly, it is handled as follows:
break
with no label, no further action is taken and the switch
statement completes normally.
switch
statement completes abruptly for the same reason. The case of abrupt completion because of a break
with a label is handled by the general rule for labeled statements (§14.6).
As in C and C++, execution of statements in a switch block "falls through labels" in Java. For example, the program:
class Toomany { static void howMany(int k) { switch (k) { case 1: System.out.print("one "); case 2: System.out.print("too "); case 3: System.out.println("many"); } }
public static void main(String[] args) { howMany(3); howMany(2); howMany(1); }
}
contains a switch block in which the code for each case falls through into the code for the next case. As a result, the program prints:
many too many one too many
If code is not to fall through case to case in this manner, then break
statements
should be used, as in this example:
class Twomany { static void howMany(int k) { switch (k) { case 1: System.out.println("one"); break; // exit the switch case 2: System.out.println("two"); break; // exit the switch case 3: System.out.println("many"); break; // not needed, but good style } }
public static void main(String[] args) { howMany(1); howMany(2); howMany(3); }
}
one two many