3.4 The switch Statement & Multi-Way Branching
Key Takeaways
- In Java SE 8, switch selector expressions permit only byte, short, char, int, their respective wrapper classes (Byte, Short, Character, Integer), String (since Java 7), and enum types.
- The data types long, float, double, and boolean (and their corresponding wrapper classes) are strictly prohibited as switch selectors and cause compile-time errors.
- Every case label must be a compile-time constant expression whose value is assignable to the selector type without narrowing, and duplicate case values are strictly forbidden.
- Omitting a break statement triggers fall-through execution, causing subsequent case bodies and default to execute sequentially without re-evaluating case conditions until a break or closing brace is reached.
- The default label is optional and may appear at any position (top, middle, or bottom) inside the switch block; it executes only if no case matches, but will fall through into subsequent cases if not terminated by break.
3.4 The switch Statement & Multi-Way Branching
[!NOTE] Exam Focus: The
switchstatement is a major focus area of Exam 1Z0-811. Key testing points include identifying valid and invalid selector types in Java SE 8, compile-time constant requirements forcaselabels, duplicate label compilation errors, fall-through execution whenbreakstatements are omitted, anddefaultlabel placement and cascading execution.
The switch statement provides multi-branch selection based on the evaluated equality of a single selector expression against multiple constant case values. It serves as a structured, optimized alternative to lengthy if-else-if chains testing the same variable for discrete values.
General Syntax
switch (selectorExpression) {
case constant1:
// statements executed when selectorExpression == constant1
break;
case constant2:
// statements executed when selectorExpression == constant2
break;
default:
// statements executed when no case matches
break;
}
1. Permissible vs. Forbidden Selector Types in Java SE 8
A cornerstone objective of the 1Z0-811 examination is verifying whether a variable type can serve as the selector expression in a switch statement.
+------------------------------------+-------------------------------------+
| PERMISSIBLE SWITCH TYPES | FORBIDDEN SWITCH TYPES |
+------------------------------------+-------------------------------------+
| byte (and Byte wrapper) | long (and Long wrapper) |
| short (and Short wrapper) | float (and Float wrapper) |
| char (and Character wrapper) | double (and Double wrapper) |
| int (and Integer wrapper) | boolean (and Boolean wrapper) |
| String (Java 7+) | Any other object type (Scanner, etc)|
| enum types (Java 5+) | |
+------------------------------------+-------------------------------------+
Rationale for Forbidden Types
long(andLong): 64-bit integer values are not permitted because switch jump tables in bytecode (tableswitchandlookupswitch) are designed specifically for 32-bit offsets.floatanddouble: Floating-point rounding inaccuracies inherent to binary IEEE 754 representations make exact equality checks unreliable.boolean: A boolean choice has only two states (trueorfalse) and is designed for anif-elsestatement; permittingswitch(boolean)would add unnecessary language complexity.
long orderId = 1000L;
// COMPILE ERROR: incompatible types: possible lossy conversion from long to int
// switch (orderId) { ... }
double taxRate = 0.08;
// COMPILE ERROR: selector type not allowed
// switch (taxRate) { ... }
2. Case Label Requirements & Compile-Time Constants
The Java compiler enforces strict grammatical rules on values following the case keyword:
1. Compile-Time Constant Requirement
Every case label must be a compile-time constant expression. A constant expression can be fully evaluated to a fixed value during compilation:
- Literal values (e.g.,
case 1:,case 'X':,case "ACTIVE":) finalvariables initialized inline with a compile-time constant- Constant arithmetic expressions (e.g.,
case 2 + 3:) - Enum constants (e.g.,
case NORTH:)
final int MIN_SCORE = 60; // Compile-time constant
int normalVar = 75; // Non-final variable
final int blankFinal; // Blank final
blankFinal = 80;
int score = 85;
switch (score) {
case MIN_SCORE: // COMPILES: MIN_SCORE is a final compile-time constant
break;
// case normalVar: // COMPILE ERROR: constant expression required
// break;
// case blankFinal: // COMPILE ERROR: blank final is NOT a compile-time constant
// break;
}
2. Range Constraints and Type Assignability
The constant expression in a case label must be assignable to the switch expression's data type without narrowing:
byte b = 10;
switch (b) {
case 100: // Compiles: 100 fits in byte (-128 to 127)
break;
// case 130: // COMPILE ERROR: possible lossy conversion from int to byte (130 exceeds byte range)
// break;
}
3. Duplicate Case Labels Are Forbidden
No two case labels in the same switch block may evaluate to the identical value:
int code = 2;
switch (code) {
case 1: break;
case 2: break;
// case 1 + 1: break; // COMPILE ERROR: duplicate case label (1 + 1 evaluates to 2)
}
3. The break Statement and Fall-Through Mechanics
The break statement halts the execution of the switch block and transfers control to the statement immediately following the switch's closing brace }.
The Fall-Through Mechanism
If a matching case block does not terminate with a break (or return), execution falls through into subsequent cases, executing their statement bodies without testing their case conditions, until a break is encountered or the switch block ends!
int day = 2;
switch (day) {
case 1:
System.out.print("Mon ");
case 2:
System.out.print("Tue "); // Matches: prints "Tue "
case 3:
System.out.print("Wed "); // Falls through: prints "Wed " (no condition check!)
break; // Halts switch execution
case 4:
System.out.print("Thu ");
}
// Output: Tue Wed
Deliberate (Intentional) Fall-Through
Developers frequently omit break statements deliberately to group multiple case labels that share common handling logic:
char grade = 'B';
switch (grade) {
case 'A':
case 'B':
case 'C':
System.out.println("Passing grade");
break;
case 'D':
case 'F':
System.out.println("Failing grade");
break;
default:
System.out.println("Invalid grade");
break;
}
4. The default Label: Placement and Execution Dynamics
The default label defines the block of code executed when no case constant matches the selector expression.
Key Rules for default
- Optional: A switch statement does not require a
defaultlabel. If no case matches and nodefaultexists, the switch executes as a no-op. - Placement Anywhere: The
defaultlabel can appear anywhere inside the switch block—at the top, in the middle, or at the bottom. - Evaluation Timing: Regardless of its textual position inside the block,
defaultis evaluated only after all case labels have failed to match. - Fall-Through from Default: If
defaultis placed anywhere other than the very bottom and omits abreak, execution cascades directly into the case labels beneath it!
int code = 99; // Does not match 1 or 2
switch (code) {
default:
System.out.print("Def "); // Evaluates because no case matches
case 1:
System.out.print("One "); // Falls through into case 1!
break;
case 2:
System.out.print("Two ");
}
// Output: Def One
[!WARNING] Exam Trap: When
defaultis at the top of a switch block, candidates often assume it executes first. It does not execute first—Java checks allcaseconstants first. However, if no case matches,defaultexecutes, and if it lacks abreak, execution cascades straight into subsequent cases!
5. Strings and Null Safety in Switch
Since Java 7, String objects can be used as switch selectors. The comparison is case-sensitive and evaluates using String.equals():
String role = "ADMIN";
switch (role) {
case "admin": // Will NOT match ("ADMIN" is uppercase)
System.out.println("User admin");
break;
case "ADMIN": // Matches
System.out.println("System administrator");
break;
}
The Null Selector Trap
If a String (or boxed wrapper object) reference holding null is passed into a switch statement, Java throws an unchecked java.lang.NullPointerException at runtime when attempting to evaluate the selector:
String status = null;
// Throws NullPointerException at runtime!
switch (status) {
case "OK":
System.out.println("OK");
break;
default:
System.out.println("Unknown");
}
6. Architectural Comparison: switch vs. if-else-if
| Architectural Feature | switch Statement | if-else-if Ladder |
|---|---|---|
| Tested Condition | Strict equality against discrete constants | Arbitrary boolean expressions (<, >, !=, &&, etc.) |
| Supported Types | byte, short, char, int, Wrappers, String, enums | Any data type evaluated via boolean expressions |
| Range Evaluation | Cannot test ranges directly (case 1..10 is invalid) | Excels at range checks (score >= 80 && score < 90) |
| Evaluated Variables | Tests only a single expression | Can evaluate multiple independent variables simultaneously |
| Bytecode Compilation | Compiled to tableswitch (O(1)) or lookupswitch (O(log n)) | Evaluated sequentially O(n) |
| Fall-Through Control | Requires explicit break to prevent fall-through | Mutually exclusive branches by default |
Which of the following variable declarations CANNOT be used as the selector expression in a Java SE 8 switch statement?
What is the console output when the following Java code executes?
int code = 2;
switch (code) {
default:
System.out.print("Def ");
case 1:
System.out.print("One ");
break;
case 2:
System.out.print("Two ");
case 3:
System.out.print("Three ");
break;
case 4:
System.out.print("Four ");
}
Consider the following Java method snippet:
Which of the following case labels causes a compile-time error if added to the switch statement?final int BASE = 10;
int offset = 5;
final int limit;
limit = 20;
int val = 15;
switch (val) {
case BASE:
System.out.println("Base");
break;
// Which case label below causes a compilation error?
}