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
switch (expression) {
case value1:
// code block
break;
case value2:
// code block
break;
default:
// code block
}
2.2 Examples
// 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
break, execution falls through to the next case. This can be intentional or a bug.
// 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
variable = switch (expression) {
case value1 -> result1;
case value2 -> result2;
default -> result3;
};
3.2 Examples
// 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;
};
4. Arrow Syntax (->)
The arrow syntax (->) provides a cleaner way to write switch cases without break statements.
4.1 Arrow Syntax in Switch Statements
// 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
// 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;
};
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
// 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
// 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 supportedboolean- Not supported (use if-else instead)- Most object types - Not supported (except String and with pattern matching)
8. Common Pitfalls
8.1 Missing Break Statements
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
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
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
whenclause 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
0 Comments