Java switch expression

Java Switch Expressions

Autor-Bild
von Sven Woltmann – 2. Februar 2022

Artikelserie: Project Amber

In Project Amber werden neue Java-Sprachfunktionen entwickelt und nach und nach veröffentlicht.

Teil 1: Switch Expressions (Java 14)

Teil 2: Text Blocks (Java 15)

Teil 3: Records (Java 16)

Teil 4: Sealed Classes (Java 17)

(Melde dich für den HappyCoders-Newsletter an,
um sofort über neue Teile informiert zu werden.)

Switch Expressions wurden in Java 14 im Rahmen von Project Amber veröffentlicht.

Bei Switch Expressions handelt es sich eigentlich um zwei Erweiterungen, die unabhängig voneinander, aber auch kombiniert, eingesetzt werden können:

  1. Pfeilnotation ohne break und fall-throughs
  2. Verwendung von switch als Ausdruck mit Rückgabewert

Schauen wir uns die Änderungen eine nach der anderen an (ich verwende dazu die Beispiele aus JEP 361, leicht abgewandelt).

Ausgangslage

Im folgenden Beispiel wird für einen Wochentag die Wortlänge ausgegeben. Für die letzten beiden Fälle habe ich den Code etwas komplizierter als nötig geschrieben – um im Folgenden zu demonstrieren, was mit Switch Expressions möglich ist.

switch (day) { case MONDAY: case FRIDAY: case SUNDAY: System.out.println(6); break; case TUESDAY: System.out.println(7); break; case THURSDAY: case SATURDAY: System.out.println((int) Math.pow(2, 3)); break; case WEDNESDAY: int three = 1 + 2; System.out.println(three * three); break; }
Code-Sprache: Java (java)

Diese Schreibweise ist zum einen unübersichtlich, zum anderen fehleranfällig aufgrund der sogenannten "Fall-Throughs", also der Ausführungsfortsetzung beim Folgefall, wenn der vorherige nicht mit einem break-Statement abgeschlossen wurde.

Entsprechend werden solche Konstrukte auch von den gängigen Tools für statische Code-Analyse (SCA) wie Sonar, Checkstyle und PMD als Code Smells moniert:

Warnungen der statischen Code-Analyse (SCA) bei Switch-Statements ohne break
Warnungen der statischen Code-Analyse (SCA) bei Switch-Statements ohne break

Switch mit Pfeilnotation

Das folgende Beispiel zeigt, wie du ab Java 14 statt des Doppelpunkts einen Pfeil verwenden kannst. Es gelten dabei folgende Regeln:

  • Vor dem Pfeil darfst du mehrere Fälle Komma-separiert auflisten.
  • Nach dem Pfeil darf dann entweder ein einzelnes Code-Statement folgen (Zeilen 2, 3 und 4) oder ein Code-Block in geschweiften Klammern (Zeilen 5 bis 8).
  • Die break Statements fallen in dieser Notation weg.

Hier der Beispiel-Code für ein switch-Statement in Pfeil-Notation:

switch (day) { case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); case TUESDAY -> System.out.println(7); case THURSDAY, SATURDAY -> System.out.println((int) Math.pow(2, 3)); case WEDNESDAY -> { int three = 1 + 2; System.out.println(three * three); } }
Code-Sprache: Java (java)

Moderne IDEs wie IntelliJ erkennen das Verbesserungspotenzial und bieten eine automatische Konvertierung in das neue Format an:

Automatische Ersetzung von 'switch' Statements
Automatische Ersetzung von 'switch' Statements

Switch als Ausdruck mit Rückgabewert

Oft verwenden wir switch, um einer Variablen einen Fall-spezifischen Wert zuzuweisen. Im folgenden Beispiel geben wir die Länge des Wochentages nicht aus, sondern speichern sie in der Variablen numLetters.

(Die letzten zwei Fälle sind wieder absichtlich umständlich geschrieben, um zu zeigen, was mit Switch Expressions möglich ist.)

int numLetters; switch (day) { case MONDAY: case FRIDAY: case SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY: case SATURDAY: numLetters = (int) Math.pow(2, 3); break; case WEDNESDAY: int three = 1 + 2; numLetters = three * three; break; default: throw new IllegalStateException("Unknown day: " + day); }
Code-Sprache: Java (java)

Damit wir die Variable im Anschluss verwenden können, müssen wir – obwohl wir jeden Wochentag abgedeckt haben – entweder die Variable vorab mit einem Standardwert belegen oder einen default-Case angeben. Andernfalls würde der Compiler mit der Fehlermeldung "Variable 'numLetters' might not have been initialized" abbrechen.

Ab Java 14 können wir dieses Statement in einen Ausdruck umwandeln. Dabei geben wir mit dem neuen Keyword yield jeweils einen Wert zurück. Das Ergebnis des Switch-Ausdrucks weisen wir dann direkt der Variablen zu:

int numLetters = switch (day) { case MONDAY: case FRIDAY: case SUNDAY: yield 6; case TUESDAY: yield 7; case THURSDAY: case SATURDAY: yield (int) Math.pow(2, 3); case WEDNESDAY: int three = 1 + 2; yield three * three; default: throw new IllegalStateException("Unknown day: " + day); };
Code-Sprache: Java (java)

yield ist ein sogenanntes "contextual keyword" und damit nur im Kontext eines switch-Ausdrucks von Bedeutung. Falls du yield in deinem Quellcode als Variablenname verwendet haben solltest – keine Sorge, das kannst du weiterhin tun. Selbst so etwas wäre erlaubt:

int yield = 5; yield yield + yield;

Kombination von Pfeilnotation und Switch-Ausdruck

Deutlich eleganter wird der eben gezeigte Switch-Ausdruck, wenn wir ihn in Pfeilnotation schreiben. Dabei können wir den Rückgabewert

  • direkt hinter den Pfeil schreiben (Zeilen 2 und 3),
  • als Ausdruck oder Methodenaufruf hinter den Pfeil schreiben (Zeile 4)
  • oder aus einem Code-Block heraus mit yield zurückgeben (Zeile 7).
int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> (int) Math.pow(2, 3); case WEDNESDAY -> { int three = 1 + 2; yield three * three; } default -> throw new IllegalStateException("Unknown day: " + day); };
Code-Sprache: Java (java)

Das komplette Refactoring vom herkömmlichen Switch Statement zur Switch Expression mit Pfeilnotation können wir unsere IDE erledigen lassen:

 Automatische Ersetzung von 'switch' Statements durch 'switch' Expressions
Automatische Ersetzung von 'switch' Statements durch 'switch' Expressions

Vollständigkeitsanalyse bei Enums

Da es sich bei der Variablen day um ein Enum handelt, kann der Compiler erkennen, dass wir alle Fälle abgedeckt haben. Somit darf der default-Case wegfallen:

int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> (int) Math.pow(2, 3); case WEDNESDAY -> { int three = 1 + 2; yield three * three; } };
Code-Sprache: Java (java)

Auch das erledigt unsere IDE gerne für uns:

Automatische Entfernung des 'default'-Falls
Automatische Entfernung des 'default'-Falls

Die Schreibweise ohne default-Fall ist nicht nur kürzer, sondern hilft uns auch bei zukünftigen Erweiterungen des Enums. Sollten wir dieses – z. B. um einen NEWDAY – erweitern, wird der Compiler uns mitteilen, dass der Switch-Ausdruck nun unvollständig ist:

Unvollständige 'switch' Expression
Unvollständige 'switch' Expression

Switch-Ausdrücke können unseren Code also auch robuster machen.

Fazit

Switch Expressions sind ein mächtiges Werkzeug. Die Pfeilnotation und die Verwendung als Ausdruck mit Rückgabewert erlauben eine deutlich kompaktere, übersichtlichere und weniger fehleranfällige Schreibweise als bisher.

Switch Expressions wurden erstmals in Java 12 als Preview-Feature vorgestellt. Im zweiten Preview in Java 13 wurde das ursprünglich zur Rückgabe von Werten verwendete Keyword break durch yield ersetzt. Mit JDK Enhancement Proposal 361 wurden Switch Expressions in Java 14 ohne weitere Änderungen als finales Feature veröffentlicht.

Wenn dir der Artikel gefallen hat, teile ihn gerne über einen der Share-Buttons und hinterlasse mir einen Kommentar: Hattest du bereits Gelegenheit die neuen Switch Expressions einzusetzen? Wenn ja, wie gefallen sie dir. Wenn nein, warum nicht?

Möchtest du informiert werden, wenn neue Artikel auf HappyCoders.eu veröffentlicht werden? Dann klicke hier, um dich für den HappyCoders.eu-Newsletter anzumelden.