☕ Java
switch Statement
The switch statement selects one of several code blocks to execute based on the value of a single expression. It is a cleaner alternative to a long if-else-if chain when choosing among multiple constant values. Java switch works with byte, short, int, char, String, and enum types. Each case label must be a compile-time constant and the optional default case handles all unmatched values.
Syntax and Basic Usage
The switch statement evaluates its expression once and jumps to the matching case label. Execution continues from that label until a break statement, a return, or the end of the switch block. The default label is optional and executes when no case matches — it can appear anywhere in the block, though placing it last is conventional.
Java
// ── Basic syntax: ────────────────────────────────────────────────────
//
// switch (expression) {
// case value1:
// // statements
// break;
// case value2:
// // statements
// break;
// default:
// // statements when no case matches
// }
// ── Day of week example: ─────────────────────────────────────────────
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"); // executes
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
default:
System.out.println("Invalid day: " + day);
}
// ── Execution trace for day = 3: ─────────────────────────────────────
// 1. Evaluate expression: day = 3
// 2. Jump to case 3:
// 3. Print "Wednesday"
// 4. Hit break → exit switch
// 5. Continue after switch block
// ── default can appear anywhere — convention is last: ─────────────────
int code = 99;
switch (code) {
default:
System.out.println("Unknown code"); // executes
break;
case 1:
System.out.println("Start");
break;
case 2:
System.out.println("Stop");
break;
}Fall-Through Behaviour
When a case label is reached and there is no break statement, execution falls through to the next case and continues running its statements regardless of whether that case's label matches. Fall-through is sometimes used intentionally to share code between cases, but accidental fall-through is one of the most common Java bugs. Always use break unless fall-through is explicitly intended, and document it with a comment.
Java
// ── Accidental fall-through — common bug: ────────────────────────────
int value = 2;
switch (value) {
case 1:
System.out.println("One");
// MISSING break — falls through to case 2!
case 2:
System.out.println("Two");
// MISSING break — falls through to case 3!
case 3:
System.out.println("Three");
break;
case 4:
System.out.println("Four");
break;
}
// Output (value = 2):
// Two ← case 2 matches
// Three ← fell through from case 2 (no break)
// (stops at break in case 3)
// ── Intentional fall-through — multiple cases share code: ────────────
int month = 4;
int daysInMonth;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
daysInMonth = 31; // intentional fall-through for 31-day months
break;
case 4:
case 6:
case 9:
case 11:
daysInMonth = 30; // intentional fall-through for 30-day months
break;
case 2:
daysInMonth = 28; // simplified — ignoring leap years
break;
default:
throw new IllegalArgumentException("Invalid month: " + month);
}
System.out.println("Days: " + daysInMonth); // Days: 30
// ── Document intentional fall-through with @SuppressWarnings: ────────
switch (value) {
case 1:
System.out.println("Preprocessing...");
// falls through intentionally
case 2:
System.out.println("Processing"); // runs for both 1 and 2
break;
default:
System.out.println("Other");
}switch with String and Enum
Java 7 added String support to switch. String comparison in switch uses equals() internally — it is case-sensitive. Enum switch is a natural fit since enum constants are compile-time constants. Both eliminate chains of if-else-if with equals() calls and produce cleaner, more readable code.
Java
// ── switch with String (Java 7+): ────────────────────────────────────
String direction = "NORTH";
switch (direction) {
case "NORTH":
System.out.println("Moving north"); // executes
break;
case "SOUTH":
System.out.println("Moving south");
break;
case "EAST":
System.out.println("Moving east");
break;
case "WEST":
System.out.println("Moving west");
break;
default:
System.out.println("Unknown direction: " + direction);
}
// ── String switch is case-sensitive: ─────────────────────────────────
String cmd = "quit";
switch (cmd.toLowerCase()) { // normalise before switching
case "start":
startService();
break;
case "stop":
stopService();
break;
case "quit":
case "exit":
System.out.println("Goodbye.");
System.exit(0);
break;
default:
System.out.println("Unknown command: " + cmd);
}
// ── switch with enum: ────────────────────────────────────────────────
enum Season { SPRING, SUMMER, AUTUMN, WINTER }
Season season = Season.SUMMER;
switch (season) {
case SPRING:
System.out.println("Flowers blooming");
break;
case SUMMER:
System.out.println("Hot and sunny"); // executes
break;
case AUTUMN:
System.out.println("Leaves falling");
break;
case WINTER:
System.out.println("Cold and snowy");
break;
// No default needed — all enum constants covered.
// Adding default is still good practice for safety.
}
// ── Returning from a method with switch: ─────────────────────────────
public static int getDaysInMonth(int month) {
switch (month) {
case 1: case 3: case 5: case 7:
case 8: case 10: case 12:
return 31;
case 4: case 6: case 9: case 11:
return 30;
case 2:
return 28;
default:
throw new IllegalArgumentException(
"Invalid month: " + month);
}
}Supported Types and Restrictions
Switch expressions must be one of a specific set of types. Floating-point types (float, double), long, and boolean are not supported. Case labels must be compile-time constants — variables, method calls, and runtime values are not permitted as case labels. Understanding these restrictions prevents common compile errors.
Java
// ── Supported switch expression types: ──────────────────────────────
//
// ✓ byte, short, int, char (and their wrapper classes)
// ✓ String (Java 7+)
// ✓ enum types (all versions)
// ✓ var (inferred as one of the above)
//
// ✗ long — not supported (use if-else or cast to int)
// ✗ float — not supported
// ✗ double — not supported
// ✗ boolean — not supported (use if-else)
// ✗ Object — not supported in traditional switch
// (Java 21 pattern switch supports Object)
// ── Case labels must be compile-time constants: ───────────────────────
final int MAX = 100; // compile-time constant (final + literal)
int limit = 50; // NOT a compile-time constant
int x = 75;
switch (x) {
case 50: // ✓ integer literal
break;
case MAX: // ✓ final variable with literal initialiser
break;
// case limit: // ✗ COMPILE ERROR — not a compile-time constant
// case x + 1: // ✗ COMPILE ERROR — runtime expression
// case getMax(): // ✗ COMPILE ERROR — method call
}
// ── Case labels must be unique: ───────────────────────────────────────
// switch (x) {
// case 1:
// break;
// case 1: // ✗ COMPILE ERROR — duplicate case label
// break;
// }
// ── Null causes NullPointerException — switch does not handle null: ───
String s = null;
// switch (s) { // ✗ throws NullPointerException at runtime
// case "a": break;
// }
// Always null-check before switch:
if (s != null) {
switch (s) {
case "hello": System.out.println("Hi"); break;
default: System.out.println("Other");
}
}
// ── char in switch: ───────────────────────────────────────────────────
char grade = 'B';
switch (grade) {
case 'A':
System.out.println("Excellent");
break;
case 'B':
System.out.println("Good"); // executes
break;
case 'C':
System.out.println("Average");
break;
default:
System.out.println("Below average");
}Practical switch Patterns
These patterns show the most common real-world uses of the traditional switch statement — HTTP status handling, menu systems, state machines, and score classification. They also demonstrate when switch improves over if-else chains and when if-else remains the better choice.
Java
// ── HTTP status code handler: ────────────────────────────────────────
public String getStatusMessage(int statusCode) {
switch (statusCode) {
case 200: return "OK";
case 201: return "Created";
case 204: return "No Content";
case 400: return "Bad Request";
case 401: return "Unauthorized";
case 403: return "Forbidden";
case 404: return "Not Found";
case 409: return "Conflict";
case 500: return "Internal Server Error";
case 503: return "Service Unavailable";
default: return "Unknown Status: " + statusCode;
}
}
// ── Console menu: ────────────────────────────────────────────────────
Scanner scanner = new Scanner(System.in);
boolean running = true;
while (running) {
System.out.println("
=== Menu ===");
System.out.println("1. Add item");
System.out.println("2. Remove item");
System.out.println("3. List items");
System.out.println("4. Exit");
System.out.print("Choice: ");
int choice = scanner.nextInt();
switch (choice) {
case 1:
addItem();
break;
case 2:
removeItem();
break;
case 3:
listItems();
break;
case 4:
running = false;
System.out.println("Goodbye.");
break;
default:
System.out.println("Invalid choice. Enter 1–4.");
}
}
// ── Simple state machine: ────────────────────────────────────────────
enum TrafficLight { RED, YELLOW, GREEN }
public TrafficLight nextState(TrafficLight current) {
switch (current) {
case RED: return TrafficLight.GREEN;
case GREEN: return TrafficLight.YELLOW;
case YELLOW: return TrafficLight.RED;
default:
throw new IllegalStateException(
"Unknown state: " + current);
}
}
// ── When to use switch vs if-else: ────────────────────────────────────
//
// PREFER switch when:
// Testing one variable against multiple EXACT values
// All values are compile-time constants
// 3 or more cases (2 cases → if-else is cleaner)
// Working with enum, String, or int/char
//
// PREFER if-else when:
// Conditions involve ranges (score > 90, age >= 18)
// Conditions test different variables
// Using long, double, float, or boolean
// Conditions involve method calls or complex expressionsRelated Topics in Control Statements
Control Statements
Control statements determine the flow of execution in a Java program. Without them, code executes line by line from top to bottom. Control statements allow the program to make decisions, repeat actions, and jump to different parts of the code based on conditions. Java provides three categories: selection statements (if, if-else, switch), iteration statements (for, while, do-while), and jump statements (break, continue, return).
if Statement
The if statement is the most fundamental control flow construct in Java. It evaluates a boolean expression and executes a block of code only if the expression is true. If the condition is false the block is skipped entirely and execution continues with the next statement after the if block.
if-else Statement
The if-else statement extends the basic if by providing an alternative block that executes when the condition is false. It guarantees that exactly one of two blocks always executes — either the if block (condition true) or the else block (condition false). The if-else-if chain extends this to choose among more than two alternatives.
Nested if
A nested if is an if statement placed inside the body of another if or else block. Nesting allows multi-level decision making — first check a broad condition, then refine with a more specific condition inside it. While nesting is sometimes necessary, deep nesting quickly reduces readability and should be refactored using guard clauses, logical operators, or extracted methods.