ZetCode

Java switch expression

last modified February 29, 2024

In this article we show how to work with switch expressions in Java.

Switch expressions offer a more concise and readable way to write multi-way branching logic. They are a powerful enhancement for the classic switch statements.

Unlike traditional switch statements, the switch expressions can return values.

Java switch expressions support using multiple case labels. These are also called arms. Each case label is followed by the -> arrow syntax.

The switch expressions must be exhaustive. With the exception of few cases such as enumerations, where the compiler can determine all possible options, we must use the default arm. It is executed when no other option matches.

Main.java
import java.util.Scanner;

void main() {

    System.out.print("Enter a domain: ");

    try (var sc = new Scanner(System.in)) {

        String domain = sc.nextLine();
        domain = domain.trim().toLowerCase();

        switch (domain) {

            case "us" -> System.out.println("United States");
            case "de" -> System.out.println("Germany");
            case "sk" -> System.out.println("Slovakia");
            case "hu" -> System.out.println("Hungary");
            default -> System.out.println("Unknown");
        }
    }
}

The user is requested to enter a domain name. The domain name is read and stored in a variable. The variable is tested with the switch keyword against a list of options. In our program, we have a domain variable. We read a value for the variable from the command line.

case "us" -> System.out.println("United States");

We use the case statement to test for the value of the variable. There are several options. If, for instance, the value equals to "us", the "United States" string is printed to the console. Once an option matches, no other arms are evaluated.

default -> System.out.println("Unknown");

The default branch is executed when the value does not match any previous branch.

Using enumerations

In the next example, we work with enumerations.

Main.java
import java.util.Random;

void main() {

    Season season = Season.randomSeason();

    String msg = switch (season) {

        case Season.SPRING -> "Spring";
        case Season.SUMMER -> "Summer";
        case Season.AUTUMN -> "Autumn";
        case Season.WINTER -> "Winter";
    };

    System.out.println(msg);
}

enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;

    public static Season randomSeason() {
        
        var random = new Random();
        int ridx = random.nextInt(Season.values().length);
        return Season.values()[ridx];
    }
}

We define a Season enumeration. The enumeration contains a randomSeason method which creates a Season value randomly. Depending on the chosen value, we print a message.

var msg = switch (season) {

    case Season.Spring -> "Spring";
    case Season.Summer -> "Summer";
    case Season.Autumn -> "Autumn";
    case Season.Winter -> "Winter";
};

System.out.println(msg);

We check the value against the switch expression. The expression returns the string representation of the enum. Note that the switch expression is exhaustive.

Checking multiple options

We can check multiple options in one branch.

Main.java
import java.util.Random;

void main() {

    Grade grade = Grade.randomGrade();

    String msg = switch (grade) {

        case Grade.A, Grade.B, Grade.C, Grade.D, Grade.E, Grade.F -> "passsed";
        case Grade.FX -> "failed";
    };

    System.out.println(STR."\{grade} - \{msg}");
}

enum Grade {
    A, B, C, D, E, F, FX;

    public static Grade randomGrade() {

        var random = new Random();
        int rdx = random.nextInt(Grade.values().length);
        return Grade.values()[rdx];
    }
}

We have a list of grades. For A throug F grades, we pass the example. For the FX grade, we fail the exam.

String msg = switch (grade) {

    case Grade.A, Grade.B, Grade.C, Grade.D, Grade.E, Grade.F -> "passsed";
    case Grade.FX -> "failed";
};

We check six options in the first branch. They are separated with a comma.

Checking types

In the following program, we check the types of values.

Main.java
import java.math.BigDecimal;
import java.util.List;

void main() {

    List<Object> objects = List.of("falcon", new BigDecimal(120001212),
            new int[] { 1, 2, 3, 4, 5 }, new String[] { "sky", "blue", "rock" });

    objects.forEach(e -> System.out.println(checkType(e)));
}

String checkType(Object o) {

    return switch (o) {
        case String str -> "String";
        case BigDecimal bd -> "BigDecimal";
        case Integer i -> "Integer";
        case int[] ai -> "Array of integers";
        case String[] as -> "Array of strings";
        default -> "n/a";
    };
}

We have a list of objects of various types. Using switch expression, we determine the type of each value.

return switch (o) {
    case String str -> "String";
    case BigDecimal bd -> "BigDecimal";
    case Integer i -> "Integer";
    case int[] ai -> "Array of integers";
    case String[] as -> "Array of strings";
    default -> "n/a";
};

After the case keyword, we provide the type. If the type matches, the arm is executed and the corresponding string is returned.

When guards

When guards can be used to apply simple expressions on options. The expressions can be compined with && and || operators.

Main.java
import java.util.Arrays;

void main() {

    int[] ages = { 12, 23, 45, 0, 67, 88, 43, 55, -4};

    Arrays.stream(ages).forEach(e -> System.out.println(STR."\{e} - \{checkAge(e)}"));
}

String checkAge(Integer age) {

    return switch (age) {
        case Integer i when i < 18 && i > 0-> "minor";
        case Integer i when i >= 18 && i < 64 -> "adult";
        case Integer i when i > 64 -> "senior";
        default -> "n/a";
    };
}

We have an array of integers representing ages. We use the switch expression to map the values into age categories.

return switch (age) {
    case Integer i when i < 18 && i > 0-> "minor";
    case Integer i when i >= 18 && i < 64 -> "adult";
    case Integer i when i > 64 -> "senior";
    default -> "n/a";
};

After the when keyword, we use the < 18 && i > 0-> expression to check if the number falls between 0 and 18.

Null values

It is possible to check for nulls in switch expressions.

Main.java
import java.util.List;
import java.util.ArrayList;

void main() {

    List<Integer> data = new ArrayList<>();
    data.add(2);
    data.add(5);
    data.add(0);
    data.add(null);
    data.add(-4);
    data.add(6);

    data.forEach(e -> System.out.println(STR."\{e} - \{checkValue(e)}"));
}

String checkValue(Integer i) {

    return switch (i) {
        case null -> "null value";
        case 0 -> "zero value";
        case Integer n when n > 0 -> "positive value";
        case Integer n when n < 0 -> "negative value";
        default -> "n/a";
    };
};

We have a list of integers; there is also one null value.

case null -> "null value";

This arm checks if the value is null.

Record fields

It is possible to check record fields in when guards.

Main.java
import java.util.List;

void main() {

    var points = List.of(Point.of(0, 0), Point.of(-3, -3), Point.of(-3, -3),
            Point.of(12, -1));

    points.forEach(p -> System.out.println(STR."\{p} - \{checkQuadrant(p)}"));
}

String checkQuadrant(Point p) {

    return switch (p) {
        case Point(var x, var y) when x == 0 && y == 0 -> "origin";
        case Point(var x, var y) when x > 0 && y > 0 -> "Q I";
        case Point(var x, var y) when x < 0 && y > 0 -> "Q II";
        case Point(var x, var y) when x < 0 && y < 0 -> "Q III";
        case Point(var x, var y) when x > 0 && y < 0 -> "Q IV";
        default -> "n/a";
    };
};

record Point(int x, int y) {
    static Point of(int x, int y) {
        return new Point(x, y);
    }
}

We have a list of points of a coordinate system. We map each point to its corresponding quadrant.

return switch (p) {
    case Point(var x, var y) when x == 0 && y == 0 -> "origin";
    case Point(var x, var y) when x > 0 && y > 0 -> "Q I";
    case Point(var x, var y) when x < 0 && y > 0 -> "Q II";
    case Point(var x, var y) when x < 0 && y < 0 -> "Q III";
    case Point(var x, var y) when x > 0 && y < 0 -> "Q IV";
    default -> "n/a";
};

The record follows the case keyword. After the when guard, we can work with the fields in expression directly.

Source

Java language - reference

In this article we were talking about switch expressions in Java.

Author

My name is Jan Bodnar and I am a passionate programmer with many years of programming experience. I have been writing programming articles since 2007. So far, I have written over 1400 articles and 8 e-books. I have over eight years of experience in teaching programming.

List all Java tutorials.