Contents

Pattern Matching for Switch

Written by: David Vlijmincx

Introduction

With Java 21, we get pattern matching for switch. In this article, we take a look at how to use it in different use cases.

Pattern matching for Switch

With Java 21, you can check against different patterns inside a switch statement. The switch statement in the following example matches against different types of cases. We can use the cases to check the type of the given object. The code in the example behaves differently when the object is of type String or Integer. If the case that the value isn't of type String or Integer, the default case is triggered.

1
2
3
4
5
Object anotherObject = switch (unknownObject) {
    case String s -> s + " the object if of type String";
    case Integer i -> i + 50;
    default -> "Unexpected value";
};

Null values

Null values are not matched against the default case. They will continue to throw a null pointer exception. In previous versions of Java, you would check this outside the Switch statement. Now we can include the null check inside the switch statement.

In the following example, the first case in the switch statement checks for null values.

1
2
3
4
5
6
String anotherObject = switch (unknownObject) {
    case null -> "the object is null";
    case String s -> s + " the object if of type String";
    default -> throw new IllegalStateException("Unexpected value: " + unknownObject);
    // default does not match null
};

Guarded case label

There are use cases where knowing the type of object is not enough, and you need to do more checks. This is now also possible inside a Switch, with what is called a guarded case label. You can see on line 3 in the following example how a guarded pattern works. Using when you can add extra conditions that have to match for that case to execute.

The following guarded case label can be less specific than the previous one. Like in the example, the first guarded case label checks if the object is of type String and contains some, the next case only checks if the type of the object is String.

1
2
3
4
5
6
7
Object anotherObject = switch (unknownObject) {
    case null -> "the object is null";
    case String s when s.contains("some") -> s + " the String contained some";
    case String s -> s + " the object is of type String";
    case Integer i -> i + 50;
    default -> throw new IllegalStateException("Unexpected value: " + unknownObject);
};

Case constants

Instead of using guarded cases, you can also use case constants. In the following example, we use case constants with Strings. Depending on the input of the switch, a different case is triggered. In the following example, if the input is a or B the first case is triggered. If the String contains any other value, it is matched against the next case till it hits one that matches.

1
2
3
4
5
String anotherString = switch (myString) {
    case "a", "B" -> " the object is a or B";
    case String s when s.contains("some") -> s + " it contains some";
    case String s -> s + " is of type String";
};

Conclusion

In this post, we took a look at how to use the switch pattern for switch.