Programming and Java Fundamentals

Switch Expressions and Statements

ReadingPreview

You are viewing a free preview lesson.

Lesson Overview

In a program, we often need to select one action from several possible actions based on the exact value of something.

For example:

  • Determine a day name from a day number
  • Perform an action based on a menu option
  • Select a dashboard based on a user role
  • Show a description based on a course level
  • Create a message based on a status

This kind of logic can also be written using if-else.

However, when checking several exact matches for the same value, switch can often be more readable.

In this lesson, we will learn:

  • What switch is
  • case and default
  • Traditional switch
  • break
  • Fall-through
  • Multiple case labels
  • Arrow-style switch
  • switch expressions
  • yield
  • Using switch with String
  • When to use if-else and when to use switch

Learning Objectives

After completing this lesson, you will be able to:

  • Explain the purpose of switch
  • Write a traditional switch
  • Use case, default, and break
  • Understand fall-through
  • Write modern arrow-style switch
  • Group multiple case labels
  • Produce a value from a switch expression
  • Use yield inside a block case
  • Choose switch for exact matching and if-else for 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
}

Here:

  • switch — determines which value is inspected
  • case — defines a possible exact match
  • break — exits the current switch
  • default — 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

case

Each case defines a possible matching value.

case 1:
case 2:

If the switch value matches a case, execution begins from that branch.

default

If no case matches, the default branch executes.

int option = 9;

switch (option) {
    case 1:
        System.out.println("Start");
        break;

    case 2:
        System.out.println("Stop");
        break;

    default:
        System.out.println("Unknown option");
}

Output:

Unknown option

default is not mandatory in every switch statement, but it is useful for handling unexpected values.

break

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.

Fall-Through

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.

int day = 6;

switch (day) {
    case 6:
    case 7:
        System.out.println("Weekend");
        break;

    default:
        System.out.println("Weekday");
}

Output:

Weekend

Here, case 6 and case 7 use the same code.

Modern Arrow-Style switch

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 break required
  • Clearer branch structure

Multiple Case Labels

In an arrow-style switch, multiple values can be grouped using commas.

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

This syntax is much clearer than traditional fall-through grouping.

Multiple Statements in One Case

If an arrow case contains multiple statements, use a block.

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");
    }
}

No break is required here either.

Switch Statement vs. Switch Expression

So far, we have used switch to execute actions.

switch (day) {
    case 1 ->
            System.out.println("Monday");

    case 2 ->
            System.out.println("Tuesday");

    default ->
            System.out.println("Invalid");
}

This is a switch statement.

In modern Java, switch can also produce a value. In that case, it is a switch expression.

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";
};

System.out.println(dayName);

Output:

Wednesday

Here, the entire switch expression produces a String value.

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

Semicolon After a Switch Expression

A switch expression is part of an assignment statement.

Therefore, it ends with a semicolon:

String result = switch (option) {
    case 1 -> "Create";
    case 2 -> "Update";
    default -> "Unknown";
};

If the final:

;

is omitted, there will be a compilation error.

Every Path Must Produce a Value

This expression:

String result = switch (option) {
    case 1 -> "Create";
    case 2 -> "Update";
    default -> "Unknown";
};

produces a compatible String value from every possible branch.

For a type such as int with many possible values, a default branch is generally needed to handle unmatched values.

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);

Possible output:

Creating course
Created

When Is yield Needed?

Simple expression:

case 1 -> "Create";

No yield is needed here.

But with a block:

case 1 -> {
    System.out.println("Creating");

    yield "Create";
}

yield is required to provide the value of the switch expression.

yield and return Are Not the Same

yield:

yield "Create";

only provides the value of the current switch expression.

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

These two values are not the same:

INSTRUCTOR
instructor

Therefore, it can be useful to normalize user input before switching on it.

String role =
        " instructor "
                .strip()
                .toUpperCase();

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"
            );
}

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);

Example: Weekday or Weekend

int dayNumber = 7;

String dayType = switch (dayNumber) {
    case 1, 2, 3, 4, 5 ->
            "Weekday";

    case 6, 7 ->
            "Weekend";

    default ->
            "Invalid day";
};

System.out.println(dayType);

Output:

Weekend

Example: Menu Selection

int option = 2;

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(action);

Output:

View courses

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, ...

Example:

switch (role) {
    case "ADMIN" -> ...
    case "INSTRUCTOR" -> ...
    case "LEARNER" -> ...
}

Use if-else When

The logic depends on ranges or complex boolean expressions.

Example:

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, if-else is clearer:

if (mark >= 80) {
    System.out.println("A");
} else if (mark >= 70) {
    System.out.println("B");
}

Decision Guide

SituationBetter Choice
Menu optionswitch
Exact roleswitch
Exact statusswitch
Day numberswitch
Fixed value → result mappingSwitch expression
Numeric rangeif-else
Age eligibilityif-else
Multiple boolean conditionsif-else

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, multiple branches may execute.

Correct:

switch (option) {
    case 1:
        System.out.println("Create");
        break;

    case 2:
        System.out.println("Update");
        break;

    default:
        System.out.println("Unknown");
}

Or use arrow-style syntax.

Duplicate Case

Invalid:

switch (option) {
    case 1 ->
            System.out.println("Create");

    case 1 ->
            System.out.println("Update");
}

The same case value cannot be duplicated.

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");

Forgetting the Semicolon After a Switch Expression

Wrong:

String result = switch (option) {
    case 1 -> "Create";
    default -> "Unknown";
}

Correct:

String result = switch (option) {
    case 1 -> "Create";
    default -> "Unknown";
};

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";
};

Using Range Logic Where Exact Matching Is Needed

Switch is appropriate for:

switch (option) {
    case 1 -> ...
    case 2 -> ...
}

But ranges such as:

80–100
70–79
60–69

are more naturally expressed using 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

Important Terms

switch

Selects a branch based on an exact value match.

case

Defines a possible matching value.

default

A fallback branch used when no case matches.

break

Exits a traditional switch.

Fall-Through

Execution continuing into the following case after a matching case.

Arrow-Style Switch

A modern switch form using -> syntax.

Switch Expression

A switch that produces a value.

yield

Produces a value from a block-style case in a switch expression.

Practice Exercise 1: Day Name

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

Rules:

1–5 → Weekday
6–7 → 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

Possible values:

ADMIN
INSTRUCTOR
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:

  1. Prints a message
  2. yields a String value from the block

Practice Exercise 8: switch or if-else?

Choose the appropriate structure for each situation:

  1. Age is 18 or above
  2. Menu option 1–4
  3. Grade from a mark
  4. User role
  5. Email verified and account active
  6. 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

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

In this lesson, we learned:

  • switch is useful for exact value matching
  • case defines a possible branch
  • default handles unmatched values
  • In a traditional switch, break prevents fall-through
  • Missing break can cause accidental execution of multiple branches
  • Arrow-style switch does not have automatic fall-through
  • Arrow-style switch does not require break
  • Multiple case labels can be grouped with commas
  • A switch expression can directly produce a value
  • A switch expression used in an assignment ends with a semicolon
  • yield is used to produce a value from a block case
  • String values can be used with switch, and matching is case-sensitive
  • switch is appropriate for exact fixed values
  • if-else is more appropriate for numeric ranges and complex boolean logic