Switch Statements and Expressions in Java

Master switch statements and expressions in Java including traditional switch, switch expressions, pattern matching, yield keyword, and arrow syntax for the OCP 21 exam.

Table of Contents

1. Switch Overview

The switch statement allows selecting one of many code blocks to execute based on the value of an expression. Java has enhanced switch with expressions, pattern matching, and arrow syntax.

1.1 Switch Evolution

  • Java 1.0: Traditional switch statement with fall-through
  • Java 5: Support for enum types
  • Java 7: Support for String type
  • Java 14: Switch expressions, arrow syntax, yield keyword
  • Java 17: Pattern matching for switch (preview)
  • Java 21: Pattern matching finalized

2. Traditional Switch Statement

The traditional switch statement uses case labels and requires break statements to prevent fall-through.

2.1 Basic Syntax

Syntax:
switch (expression) {
    case value1:
        // code block
        break;
    case value2:
        // code block
        break;
    default:
        // code block
}

2.2 Examples

Example:
// Integer switch
int day = 3;
String dayName;

switch (day) {
    case 1:
        dayName = "Monday";
        break;
    case 2:
        dayName = "Tuesday";
        break;
    case 3:
        dayName = "Wednesday";
        break;
    case 4:
        dayName = "Thursday";
        break;
    case 5:
        dayName = "Friday";
        break;
    case 6:
        dayName = "Saturday";
        break;
    case 7:
        dayName = "Sunday";
        break;
    default:
        dayName = "Invalid day";
}

// String switch
String color = "red";
String message;

switch (color) {
    case "red":
        message = "Stop";
        break;
    case "yellow":
        message = "Caution";
        break;
    case "green":
        message = "Go";
        break;
    default:
        message = "Unknown color";
}

// Enum switch
enum Status { PENDING, APPROVED, REJECTED }
Status status = Status.APPROVED;

switch (status) {
    case PENDING:
        System.out.println("Waiting for approval");
        break;
    case APPROVED:
        System.out.println("Approved");
        break;
    case REJECTED:
        System.out.println("Rejected");
        break;
}

2.3 Fall-Through Behavior

Important: Without break, execution falls through to the next case. This can be intentional or a bug.
Example:
// Intentional fall-through
int month = 2;
int days;

switch (month) {
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12:
        days = 31;
        break;
    case 4:
    case 6:
    case 9:
    case 11:
        days = 30;
        break;
    case 2:
        days = 28;  // Simplified (not accounting for leap years)
        break;
    default:
        days = 0;
}

3. Switch Expression (Java 14+)

Switch expressions return a value and don't require break statements. They are exhaustive (must cover all cases or have default).

3.1 Basic Syntax

Syntax:
variable = switch (expression) {
    case value1 -> result1;
    case value2 -> result2;
    default -> result3;
};

3.2 Examples

Example:
// Simple switch expression
int day = 3;
String dayName = switch (day) {
    case 1 -> "Monday";
    case 2 -> "Tuesday";
    case 3 -> "Wednesday";
    case 4 -> "Thursday";
    case 5 -> "Friday";
    case 6 -> "Saturday";
    case 7 -> "Sunday";
    default -> "Invalid day";
};

// Returning different types (must be compatible)
String color = "red";
String message = switch (color) {
    case "red" -> "Stop";
    case "yellow" -> "Caution";
    case "green" -> "Go";
    default -> "Unknown";
};

// Multiple case labels
int month = 2;
int days = switch (month) {
    case 1, 3, 5, 7, 8, 10, 12 -> 31;
    case 4, 6, 9, 11 -> 30;
    case 2 -> 28;
    default -> 0;
};
Key Features: Switch expressions must be exhaustive (cover all possible values or have default), return a value, and don't allow fall-through.

4. Arrow Syntax (->)

The arrow syntax (->) provides a cleaner way to write switch cases without break statements.

4.1 Arrow Syntax in Switch Statements

Example:
// Switch statement with arrow syntax
int day = 3;

switch (day) {
    case 1 -> System.out.println("Monday");
    case 2 -> System.out.println("Tuesday");
    case 3 -> System.out.println("Wednesday");
    case 4 -> System.out.println("Thursday");
    case 5 -> System.out.println("Friday");
    case 6 -> System.out.println("Saturday");
    case 7 -> System.out.println("Sunday");
    default -> System.out.println("Invalid day");
}

// Multiple statements with block
int value = 5;
switch (value) {
    case 1 -> {
        System.out.println("One");
        System.out.println("First");
    }
    case 2 -> {
        System.out.println("Two");
        System.out.println("Second");
    }
    default -> System.out.println("Other");
}

4.2 Arrow Syntax Benefits

  • No fall-through behavior
  • More concise syntax
  • Can be used in both statements and expressions
  • Supports multiple case labels

5. Yield Keyword

The yield keyword is used in switch expressions to return a value from a case block.

5.1 Using Yield

Example:
// Using yield in switch expression
int day = 3;
String dayName = switch (day) {
    case 1 -> "Monday";  // Simple arrow syntax
    case 2 -> "Tuesday";
    case 3 -> {
        // Block with multiple statements
        System.out.println("Processing Wednesday");
        yield "Wednesday";  // Must yield a value
    }
    case 4 -> "Thursday";
    default -> "Unknown";
};

// Complex logic with yield
int score = 85;
String grade = switch (score / 10) {
    case 10, 9 -> {
        if (score == 100) {
            yield "Perfect A";
        }
        yield "A";
    }
    case 8 -> "B";
    case 7 -> "C";
    case 6 -> "D";
    default -> "F";
};

// Yield with calculations
int month = 2;
int days = switch (month) {
    case 1, 3, 5, 7, 8, 10, 12 -> 31;
    case 4, 6, 9, 11 -> 30;
    case 2 -> {
        // Could add leap year calculation here
        yield 28;
    }
    default -> 0;
};
Important: yield is only used in switch expressions (not statements). Each case block must yield a value of the same type.

6. Pattern Matching in Switch

Pattern matching in switch (Java 17 preview, finalized in Java 21) allows matching against types and extracting values.

6.1 Type Pattern Matching

Example:
// Pattern matching with instanceof (Java 16+)
Object obj = "Hello";

if (obj instanceof String str) {
    System.out.println(str.toUpperCase());  // str is automatically cast
}

// Pattern matching in switch (Java 17+)
Object value = 42;
String result = switch (value) {
    case String s -> "String: " + s;
    case Integer i -> "Integer: " + i;
    case Double d -> "Double: " + d;
    case null -> "Null value";
    default -> "Unknown type";
};

// Pattern matching with guards
Object obj2 = "Hello";
String result2 = switch (obj2) {
    case String s when s.length() > 5 -> "Long string: " + s;
    case String s -> "Short string: " + s;
    case Integer i when i > 0 -> "Positive integer: " + i;
    case Integer i -> "Non-positive integer: " + i;
    default -> "Other";
};

6.2 Sealed Classes with Pattern Matching

Example:
// Sealed class hierarchy
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double base, double height) implements Shape {}

// Pattern matching with sealed classes
Shape shape = new Circle(5.0);
double area = switch (shape) {
    case Circle c -> Math.PI * c.radius() * c.radius();
    case Rectangle r -> r.width() * r.height();
    case Triangle t -> 0.5 * t.base() * t.height();
    // No default needed - all cases covered
};

7. Switchable Types

Not all types can be used in switch expressions. The switch expression must be of a specific type.

7.1 Supported Types

Type Since Notes
byte, short, int, char Java 1.0 Primitive types
Byte, Short, Integer, Character Java 5 Wrapper classes (auto-unboxed)
enum Java 5 Enum types
String Java 7 String literals
Object (pattern matching) Java 17+ With type patterns

7.2 Unsupported Types

  • long, float, double - Not supported
  • boolean - Not supported (use if-else instead)
  • Most object types - Not supported (except String and with pattern matching)
Note: For unsupported types, use if-else statements or convert to a supported type.

8. Common Pitfalls

8.1 Missing Break Statements

Common Mistake:
int day = 1;
String dayName;

switch (day) {
    case 1:
        dayName = "Monday";
        // Missing break - falls through!
    case 2:
        dayName = "Tuesday";
        break;
}

// dayName will be "Tuesday" instead of "Monday"
// Solution: Use arrow syntax or add break

8.2 Non-Exhaustive Switch Expression

Common Mistake:
enum Status { PENDING, APPROVED, REJECTED }
Status status = Status.PENDING;

// WRONG: Missing cases
String message = switch (status) {
    case PENDING -> "Waiting";
    case APPROVED -> "Approved";
    // Missing REJECTED - compilation error!
};

// CORRECT: Include all cases or default
String message2 = switch (status) {
    case PENDING -> "Waiting";
    case APPROVED -> "Approved";
    case REJECTED -> "Rejected";
    // OR use default
};

8.3 Null Handling

Common Mistake:
String color = null;

// WRONG: NullPointerException
switch (color) {
    case "red" -> System.out.println("Red");
    case "blue" -> System.out.println("Blue");
    default -> System.out.println("Other");
}

// CORRECT: Handle null explicitly (Java 17+)
switch (color) {
    case "red" -> System.out.println("Red");
    case "blue" -> System.out.println("Blue");
    case null -> System.out.println("Null color");
    default -> System.out.println("Other");
}

// OR check before switch
if (color != null) {
    switch (color) {
        // cases
    }
}

9. Exam Key Points

Critical Concepts for OCP 21 Exam:

  • Traditional Switch: Uses case labels and break statements, allows fall-through
  • Switch Expression: Returns a value, must be exhaustive, no fall-through
  • Arrow Syntax: case value -> result, cleaner and prevents fall-through
  • Yield Keyword: Used in switch expressions to return values from case blocks
  • Pattern Matching: Match against types and extract values (Java 17+)
  • Supported Types: byte, short, int, char, their wrappers, enum, String, Object (with patterns)
  • Unsupported Types: long, float, double, boolean
  • Fall-Through: Traditional switch falls through without break, arrow syntax prevents it
  • Exhaustiveness: Switch expressions must cover all cases or have default
  • Multiple Case Labels: case 1, 2, 3 -> result
  • Null Handling: Can explicitly handle null in switch (Java 17+)
  • Guards: Use when clause for additional conditions in pattern matching
  • Sealed Classes: Pattern matching with sealed classes ensures exhaustiveness
  • Block Syntax: Use {} for multiple statements in arrow syntax
  • Type Compatibility: All case results must be compatible with switch expression type

Post a Comment

0 Comments