Switch Expressions and Statements
Choose one action from many with traditional and arrow-style `switch`, and produce values with `switch` expressions and `yield`.
Vaatad tasuta eelvaate õppetundi.
Lesson Overview
Programs often pick one action from several based on the exact value of something: a day name from a day number, an action from a menu option, a dashboard from a user role.
This can be written with if-else, but a long chain of option == 1, option == 2, … hides the fact that we are checking one value against a list. When checking several exact matches for the same value, switch is often more readable. Java has an older form with a well-known trap (fall-through) and a modern form that avoids it and can even produce a value; we will learn both, and when if-else is still the better tool.
Learning Objectives
After completing this lesson, you will be able to:
- Explain the purpose of
switch - Write a traditional
switch - Use
case,default, andbreak - Understand fall-through
- Write modern arrow-style
switch - Group multiple case labels
- Produce a value from a
switchexpression - Use
yieldinside a block case - Choose
switchfor exact matching andif-elsefor range-based logic
What Is switch?
switch is a control-flow structure. It evaluates a value and executes the matching case branch.
int dayNumber = 2;
switch (dayNumber) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
default:
System.out.println("Invalid day");
}
Output:
Tuesday
Here, the value of dayNumber is 2, so case 2: matches.
Basic Structure
Traditional syntax:
switch (value) {
case firstValue:
// Statements
break;
case secondValue:
// Statements
break;
default:
// Statements
}
switch— determines which value is inspectedcase— defines a possible exact matchbreak— exits the current switchdefault— executes when no case matches
Traditional switch
A menu example:
int option = 2;
switch (option) {
case 1:
System.out.println("Create course");
break;
case 2:
System.out.println("View courses");
break;
case 3:
System.out.println("Exit");
break;
default:
System.out.println("Invalid option");
}
Output:
View courses
Each case, such as case 1: or case 2:, defines a possible matching value. If the switch value matches a case, execution begins from that branch. If no case matches (for example option = 9), the default branch executes and prints Invalid option.
default is not mandatory in every switch statement, but it is useful for handling unexpected values.
break and Fall-Through
In a traditional switch, break exits the switch after the matching branch has executed:
case 1:
System.out.println("Monday");
break;
Without break, execution can continue into the code of the following case. This behavior is called fall-through.
int option = 1;
switch (option) {
case 1:
System.out.println("One");
case 2:
System.out.println("Two");
case 3:
System.out.println("Three");
default:
System.out.println("Done");
}
Output:
One
Two
Three
Done
After case 1 matches, there is no break, so execution continues through the statements below it.
Accidental Fall-Through
Suppose:
int day = 2;
switch (day) {
case 1:
System.out.println("Monday");
case 2:
System.out.println("Tuesday");
case 3:
System.out.println("Wednesday");
}
The output will be:
Tuesday
Wednesday
If the expected output is only Tuesday, then this is a bug. When using traditional syntax, add the required break statements:
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
}
Multiple Cases with the Same Action
In a traditional switch, several cases can share the same behavior. Here, case 6 and case 7 use the same code:
int day = 6;
switch (day) {
case 6:
case 7:
System.out.println("Weekend");
break;
default:
System.out.println("Weekday");
}
Output:
Weekend
Modern Arrow-Style switch
Since Java 14, and so in Java 21, we can use a cleaner arrow syntax for switch.
int day = 2;
switch (day) {
case 1 -> System.out.println("Monday");
case 2 -> System.out.println("Tuesday");
case 3 -> System.out.println("Wednesday");
default -> System.out.println("Invalid day");
}
Output:
Tuesday
Important advantages of arrow-style syntax:
- No automatic fall-through
- No
breakrequired - Clearer branch structure
Multiple Case Labels
In an arrow-style switch, multiple values can be grouped using commas. This syntax is much clearer than traditional fall-through grouping.
int day = 6;
switch (day) {
case 1, 2, 3, 4, 5 -> System.out.println("Weekday");
case 6, 7 -> System.out.println("Weekend");
default -> System.out.println("Invalid day");
}
Output:
Weekend
Multiple Statements in One Case
If an arrow case contains multiple statements, use a block. No break is required here either.
int option = 1;
switch (option) {
case 1 -> {
System.out.println("Creating course");
System.out.println("Opening course form");
}
case 2 -> {
System.out.println("Loading courses");
System.out.println("Displaying course list");
}
default -> {
System.out.println("Invalid option");
}
}
Switch Statement vs. Switch Expression
So far, we have used switch to execute actions, such as printing a day name. This is a switch statement. In modern Java, switch can also produce a value. In that case, it is a switch expression. Here, the entire switch expression produces a String value:
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";
};
System.out.println(dayName);
Output:
Wednesday
Why Is a Switch Expression Useful?
Traditional version:
String dayName;
switch (day) {
case 1:
dayName = "Monday";
break;
case 2:
dayName = "Tuesday";
break;
default:
dayName = "Invalid";
}
Switch expression:
String dayName = switch (day) {
case 1 -> "Monday";
case 2 -> "Tuesday";
default -> "Invalid";
};
The second version is:
- Shorter
- Clearer about assignment
- Free from accidental fall-through
- Able to initialize the variable directly
Rules for Switch Expressions
Semicolon After a Switch Expression
A switch expression is part of an assignment statement, so it ends with a semicolon. If the final ; is omitted, there will be a compilation error.
String result = switch (option) {
case 1 -> "Create";
case 2 -> "Update";
default -> "Unknown";
};
Every Path Must Produce a Value
The expression above produces a compatible String value from every possible branch.
A switch expression must be exhaustive: it must handle every possible value of the selector. For a type such as int or String, the cases cannot list every possible value, so a default branch is required. Without it, the code does not compile.
yield
Inside an arrow case block, yield is used to produce a value after executing multiple statements.
int option = 1;
String result = switch (option) {
case 1 -> {
System.out.println("Creating course");
yield "Created";
}
case 2 -> {
System.out.println("Updating course");
yield "Updated";
}
default -> {
System.out.println("Unknown option");
yield "Unknown";
}
};
System.out.println(result);
Output:
Creating course
Created
When Is yield Needed?
A simple expression such as case 1 -> "Create"; needs no yield. But with a block, yield is required to provide the value of the switch expression:
case 1 -> {
System.out.println("Creating");
yield "Create";
}
yield and return Are Not the Same
yield "Create"; only provides the value of the current switch expression, while return exits the entire method. They are different concepts.
Using switch with String
You can also switch on exact text values.
String role = "INSTRUCTOR";
switch (role) {
case "ADMIN" -> System.out.println("Admin dashboard");
case "INSTRUCTOR" -> System.out.println("Instructor dashboard");
case "LEARNER" -> System.out.println("Learner dashboard");
default -> System.out.println("Unknown role");
}
Output:
Instructor dashboard
String Matching Is Case-Sensitive
INSTRUCTOR and instructor are not the same value, so the user input instructor would reach default. Normalize input before switching on it: with String role = " instructor ".strip().toUpperCase();, the same switch prints Instructor dashboard.
Mapping with a Switch Expression
A switch expression is useful for mapping one exact value to another value.
String level = "BEGINNER";
String description = switch (level) {
case "BEGINNER" -> "No previous experience required";
case "INTERMEDIATE" -> "Basic programming knowledge required";
case "ADVANCED" -> "Strong programming knowledge required";
default -> "Unknown course level";
};
System.out.println(description);
Output:
No previous experience required
switch or if-else?
Both control program flow, but they are useful for different situations.
Use switch When
You need to select a branch based on an exact match of one value, for example:
Option = 1, 2, 3
Role = ADMIN, INSTRUCTOR, LEARNER
Status = DRAFT, PUBLISHED, ARCHIVED
Day = 1, 2, 3, ...
switch (role) {
case "ADMIN" -> ...
case "INSTRUCTOR" -> ...
case "LEARNER" -> ...
}
Use if-else When
The logic depends on ranges or complex boolean expressions:
if (mark >= 80) {
System.out.println("A");
} else if (mark >= 70) {
System.out.println("B");
}
Another example:
if (age >= 18 && emailVerified && !accountBlocked) {
System.out.println("Enrollment allowed");
}
Ranges Are Not Direct case Values
You cannot write:
switch (mark) {
case mark >= 80:
}
Here, case is being used for exact matching. For range-based logic such as grades, the if-else chain shown above is clearer.
Decision Guide
| Situation | Better Choice |
|---|---|
| Menu option | switch |
| Exact role | switch |
| Exact status | switch |
| Day number | switch |
| Fixed value → result mapping | Switch expression |
| Numeric range | if-else |
| Age eligibility | if-else |
| Multiple boolean conditions | if-else |
Complete Interactive Example
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("1. Create course");
System.out.println("2. View courses");
System.out.println("3. Update course");
System.out.println("4. Exit");
System.out.print("Choose an option: ");
int option = Integer.parseInt(scanner.nextLine().strip());
String action = switch (option) {
case 1 -> "Create course";
case 2 -> "View courses";
case 3 -> "Update course";
case 4 -> "Exit";
default -> "Invalid option";
};
System.out.println("Selected: " + action);
scanner.close();
}
}
Possible interaction:
1. Create course
2. View courses
3. Update course
4. Exit
Choose an option: 2
Selected: View courses
Predict the Result
Question 1
int day = 2;
switch (day) {
case 1:
System.out.println("Monday");
case 2:
System.out.println("Tuesday");
case 3:
System.out.println("Wednesday");
break;
default:
System.out.println("Other day");
}
What does this print?
Answer
Tuesday
Wednesday
case 2 matches, and without a break execution falls through into case 3. The break there stops it before default.
Question 2
int day = 2;
switch (day) {
case 1 -> System.out.println("Monday");
case 2 -> System.out.println("Tuesday");
case 3 -> System.out.println("Wednesday");
default -> System.out.println("Other day");
}
What does this print?
Answer
Tuesday. Arrow-style cases never fall through, so no break is needed.
Question 3
int day = 2;
String name = switch (day) {
case 1 -> "Monday";
case 2 -> "Tuesday";
};
System.out.println(name);
Will it compile?
Answer
No: the switch expression does not cover all possible input values. A switch expression must produce a value for every possible int, so it needs a default case.
Question 4
String role = "Admin";
String access = switch (role) {
case "admin" -> "Full access";
case "student" -> "Course access";
default -> "No access";
};
System.out.println(access);
What does this print?
Answer
No access. String cases are case-sensitive, so "Admin" does not match "admin". Normalize the value first, for example with role.toLowerCase().
Common Mistakes
Missing break in Traditional Switch
Wrong:
switch (option) {
case 1:
System.out.println("Create");
case 2:
System.out.println("Update");
default:
System.out.println("Unknown");
}
If option = 1, all three branches execute and print Create, Update and Unknown. Add a break to every case (as in Accidental Fall-Through above), or use arrow-style syntax, which never falls through.
Duplicate Case
Invalid:
switch (option) {
case 1 -> System.out.println("Create");
case 1 -> System.out.println("Update");
}
The same case value cannot be duplicated: the compiler reports duplicate case label.
Wrong Case Type
int option = 1;
switch (option) {
case "1" -> System.out.println("One");
}
option is an integer, but the case value is a String. Correct:
case 1 -> System.out.println("One");
Missing yield in a Block Case
Wrong:
String result = switch (option) {
case 1 -> {
System.out.println("Creating");
}
default -> "Unknown";
};
A branch of a switch expression must produce a value. Correct:
String result = switch (option) {
case 1 -> {
System.out.println("Creating");
yield "Create";
}
default -> "Unknown";
};
Practice Exercise 1: Day Name
Solutions: lesson 1.24.
Use a day number:
1 → Monday
2 → Tuesday
3 → Wednesday
4 → Thursday
5 → Friday
6 → Saturday
7 → Sunday
Handle invalid values.
Practice Exercise 2: Weekday or Weekend
Map 1–5 to Weekday and 6–7 to Weekend. Use multiple case labels and a switch expression.
Practice Exercise 3: Menu
Menu:
1. Create course
2. View courses
3. Update course
4. Exit
Print the action based on the selected option.
Practice Exercise 4: Grade Description
Use a char value:
A → Excellent
B → Very good
C → Good
D → Needs improvement
F → Failed
Create the description using a switch expression.
Practice Exercise 5: Role
The possible values are ADMIN, INSTRUCTOR and LEARNER. Normalize the input and return the appropriate dashboard name.
Practice Exercise 6: Traditional to Arrow Style
Rewrite:
switch (option) {
case 1:
System.out.println("Create");
break;
case 2:
System.out.println("Update");
break;
default:
System.out.println("Unknown");
}
Practice Exercise 7: yield
Write a switch expression where one case:
- Prints a message
yields a String value from the block
Practice Exercise 8: switch or if-else?
Choose the appropriate structure for each situation:
- Age is
18or above - Menu option
1–4 - Grade from a mark
- User role
- Email verified and account active
- Day number
Knowledge Check
Question 1
When is switch useful?
Question 2
What is a case?
Question 3
When does default execute?
Question 4
Why is break used in a traditional switch?
Question 5
What is fall-through?
Question 6
Is break required in an arrow-style switch?
Question 7
How can multiple case labels be written?
Question 8
What is the difference between a switch statement and a switch expression?
Question 9
Does a switch expression require a semicolon at the end?
Question 10
When is yield used?
Question 11
Is String switching case-sensitive?
Question 12
Which is generally more suitable for exact value matching: switch or if-else?
Question 13
Which is generally more suitable for numeric ranges?
Question 14
Are duplicate case values valid?
Knowledge Check Answers
Answer 1
switch is useful when selecting one branch from multiple branches based on an exact match of a value.
Answer 2
A case defines a possible matching value and its branch.
Answer 3
When no case matches.
Answer 4
To exit the switch after the matching branch and prevent unwanted fall-through.
Answer 5
Fall-through means execution continues into the code of following cases after a matching case.
Answer 6
No.
Answer 7
Separate them with commas: case 1, 2, 3 -> ...
Answer 8
A switch statement executes an action. A switch expression can produce a value.
Answer 9
Yes.
String result = switch (...) {
// cases
};
Answer 10
yield is used to produce a value from a block-style case in a switch expression.
Answer 11
Yes.
Answer 12
switch.
Answer 13
if-else.
Answer 14
No.
Lesson Summary
switchselects a branch based on an exact match of one value, anddefaulthandles values that nocasematches.- In a traditional
switch,breakexits the switch. Without it, execution falls through into the following cases. - Arrow-style cases (
->) do not fall through and need nobreak. - Group several values in one arrow case with commas:
case 6, 7 -> .... - A switch expression produces a value, ends with a semicolon, and must handle every possible value, usually with
default. - Use
yieldto produce a value from a block case in a switch expression. - Normalize String input before switching on it, because String matching is case-sensitive.
- Use
switchfor exact values andif-elsefor ranges and complex conditions.
Mõtle enne
TulekulKontrollküsimused, mille puhul valid vastuse enne, kui õppetund selle näitab.