switch Statements
Dispatching on one value with case, break, and default
if / else if chains are a general tool — they handle ranges, compound conditions, anything. But when you are dispatching on a single discrete value (a day number, a menu choice, a command name), a long if-else-if starts feeling ceremonial. Java has a dedicated construct for exactly that case: switch.
In a nutshell
A switch statement looks at one value and jumps to the matching case label. You list the possible values; Java picks the right one. Every case ends with break — otherwise execution falls through into the next case, which is almost always a bug and occasionally a deliberate grouping.
switch works on int, char, String (Java 7+), and enum. It does not work on ranges like score >= 90 — for those, stick with if / else if.
By the end of this lesson you will be able to write a switch with multiple cases and a default branch, recognize when a missing break causes fall-through, and decide when to reach for switch versus if / else if.
Quick reference
Syntax
switch (expression) {
case value1:
// statements run when expression == value1
break;
case value2:
// statements run when expression == value2
break;
default:
// statements run when no case matched
break;
}
Rules
| Rule | Reason |
|---|---|
expression type is int, char, String, or enum |
Java’s switch doesn’t accept other types. |
Each case label must be a compile-time constant |
You cannot write case score > 90: or case someVar: where someVar isn’t final. |
break terminates a case and exits the switch |
Without it, execution falls into the next case. |
default handles any value not matched |
Optional, but almost always worth including. |
When to reach for switch vs if/else if
Use switch when… |
Use if / else if when… |
|---|---|
| Dispatching on one discrete value (equality) | Conditions involve ranges like score >= 90 |
| 3+ distinct single-value cases | Conditions mix multiple variables |
| Case values are constants at compile time | Conditions are computed or use method calls |
Deep dive
1. Anatomy of a switch
int day = 3;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
default:
System.out.println("Weekend");
break;
}
Java evaluates day once, then jumps to the matching case. For day = 3, execution enters case 3, prints Wednesday, hits break, and exits the switch. Nothing else runs — even though there are cases below it.
For day = 7, no case matches. Java falls through to default and prints Weekend. This is exactly why default is worth including — it makes the “none of the above” case explicit, and it prevents silent do-nothing behavior on unexpected input.
Case labels must be constants. You cannot put an expression there:
switch (score) {
case score > 90: // compile error — not a constant
...
}
case labels must be values known at compile time — a literal like 1, 'A', or "quit", or a final variable initialized with a literal. For range-based conditions like score >= 90, you need if / else if.
2. Fall-through — bug or feature
Forget a break, and execution “falls through” to the next case:
int day = 1;
switch (day) {
case 1:
System.out.println("Monday");
// NO break — execution continues into case 2
case 2:
System.out.println("Tuesday");
break;
}
Output: Monday and Tuesday. That is almost never what you want.
Intentional fall-through is a rare but useful pattern for grouping cases that share a body:
int day = 6;
switch (day) {
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("Weekday");
break;
case 6:
case 7:
System.out.println("Weekend");
break;
}
Cases 1–4 are empty — they fall through to the shared body in case 5. This is valid Java and a legitimate way to group cases. But always comment when you do it intentionally (// fall through) so a reader can tell the difference between “grouped on purpose” and “forgot a break.”
Self-check. For
day = 2, what does this print?switch (day) { case 1: System.out.println("A"); case 2: System.out.println("B"); case 3: System.out.println("C"); }Answer
Prints
BthenC.day = 2jumps to case 2, printsB, but there is no break — execution falls through to case 3 and printsC. Then the switch ends.
grade = 'A'?
switch (grade) {
case 'A': System.out.print("4.0 ");
case 'B': System.out.print("3.0 ");
case 'C': System.out.print("2.0 ");
default: System.out.print("unknown");
}break. Execution enters case 'A', prints 4.0 , then falls through into case 'B' (prints 3.0 ), then case 'C' (prints 2.0 ), then default (prints unknown). Adding break after every case produces the intended behavior.
3. When switch, when if/else if
Here’s the same decision expressed both ways:
// if/else if — readable but ceremonial
if (command.equals("quit")) {
// quit
} else if (command.equals("help")) {
// help
} else if (command.equals("save")) {
// save
} else {
// unknown
}
// switch — same behavior, shape is more visible
switch (command) {
case "quit":
// quit
break;
case "help":
// help
break;
case "save":
// save
break;
default:
// unknown
break;
}
The switch version reads as a table: here’s the variable, here are the cases, here’s the default. That shape communicates intent better when you have several equality checks on one value.
switchonStringis case-sensitive. Under the hood, aStringswitch uses.equals()semantics — so"quit"does not match"Quit"or"QUIT". If a user typesQuitand your switch lists onlycase "quit":, execution falls through todefaultand the quit branch never runs. Two fixes, depending on what you want:// (a) normalize before the switch — use this if you want case-insensitive matching switch (command.toLowerCase()) { case "quit": ...; break; case "help": ...; break; default: ...; break; } // (b) stick with case-sensitive and list only the exact spellings you accept switch (command) { case "quit": ...; break; // "Quit" and "QUIT" are rejected to default default: ...; break; }Choice (a) is the common one for user input; choice (b) is right when the input is machine-produced and the exact spelling matters.
Prefer if / else if when:
- Conditions involve ranges:
if (score >= 90) ... else if (score >= 80) ... - Conditions mix multiple variables:
if (age >= 18 && hasID) ... - Conditions are computed or use method calls that aren’t simple equality.
switch is purpose-built for “dispatch on one value.” Don’t force it into general-purpose use.
Self-check. For each decision below, is
switchorif / else ifthe better fit?
- Classifying a temperature as
freezing,cold,warm,hotbased on numeric ranges.- Converting a numeric day-of-week (1–7) to its English name.
- Applying a discount based on whether
customerTypeis"vip","member","guest", or"staff".Answer
(1) if/else if — it’s a range classification. (2) switch — discrete dispatch on one value. (3) switch — discrete dispatch on one String value across a small set.
Reflection. When would you reach for a
switchover an if/else-if chain, and when would you reach for an if/else-if chain even though aswitchwould technically work? What does your answer suggest about why Java keeps two constructs that overlap in what they can express?
Before you leave
switch is a specialized tool. It reads well for discrete dispatch on one value with three or more cases. For ranges, compound conditions, or anything more general, if / else if stays the default. Put break on every case that isn’t an intentional fall-through, and comment the ones that are.
Next: the ternary operator, Java’s one-line alternative to if/else when you just want to choose between two values.
Want to practice? The Week 3 quiz-prep set on the practice platform includes past Reges midterm items covering both switch and the ternary.