Java hat seit Version 1.0 eine switch-Anweisung zum Kontrollfluss. Im Wesentlichen basiert die Syntax auf der Programmiersprache C, die auf die 1970er Jahre zurückgeht. In Java 12 wurde eine neue Syntax probeweise eingeführt, in Java 13 verändert und in Java 14 endgültig integriert.
Insgesamt kann switch in vier Formen auftauchen:
Anweisung/Ausdruck |
Ab Java-Version |
Syntax |
Durchfall |
vollständige Abdeckung |
Anweisung |
1.0 |
: |
Ja |
Nein |
Anweisung |
14 |
-> |
Nein |
Nein |
Ausdruck |
14 |
: |
Ja |
Ja |
Ausdruck |
14 |
-> |
Nein |
Ja |
Vier Typen von switch
Den ersten Typ haben wir schon ausgiebig betrachtet, schauen wir uns die weiteren Varianten an.
Vereinfachte Switch-Anweisung, kein Durchfall, keine vollständige Abdeckung
Bei der vereinfachten switch-Anweisung steht hinter dem Label bzw. default kein Doppelpunkt, sondern ein ->. Dieser hat nichts mit Lambda-Ausdrucken zu tun, auch wenn die Symbole gleich sind. Hinter dem Pfeil steht entweder ein Ausdruck, ein Block in geschweiften Klammern oder ein throw-Anweisung, die eine Ausnahme auslöst. Implizit beendet ein break jeden Zweig, es gibt also kein Durchfallen mehr.
Beispiel
String operator = "+";
switch ( operator ) {
case "+" -> System.out.println( "Plus" );
case "-" -> { String minus = "Minus"; System.out.println( minus ); }
}
Dadurch, dass bei mehreren Anweisungen immer Blöcke gesetzt werden müssen, tritt eine lokale Variable auch nicht aus dem Bereich aus.
Ein default kann gesetzt werden, muss aber nicht. Das switch muss nicht jede Möglichkeit abdecken, was bei Zahlen und Strings eh nicht funktioniert.
Beispiel
String operator = "+";
switch ( operator ) {
case "+" -> System.out.println( "Plus" );
case "-" -> System.out.println( "Minus" );
default -> System.out.println( "Unbekannter Operator" );
}
Bei vereinfachten switch-Anweisungen sind mehrere Labels möglich, die die gleiche Behandlung haben. Kommas trennen die Labels.
Beispiel
String operator = "+";
switch ( operator ) {
case "+" -> System.out.println( "Plus" );
case "*", "×" -> System.out.println( "Mal" );
}
Switch-Ausdrücke, kein Durchfall, vollständige Abdeckung
Traditionell finden sich die Fallunterscheidungen mit switch als Anweisung und Anweisungen geben nichts zurück. In Java 14 ist es möglich, switch als Ausdruck mit Ergebnis zu nutzen.
Beispiel
String operator = "+";
String writtenOperator = (switch ( operator ) {
case "+" -> "Plus";
case "-" -> "Minus";
default -> "Unbekannter Operator";
} ).toUpperCase();
System.out.println( writtenOperator );
Ausdrücke müssen immer Ergebnisse liefern, und folglich muss switch immer einen Pfad auf einen Wert nehmen. Der übliche Fall ist default wie gezeigt, es gibt allerdings Sonderfälle, wie bei Aufzählungen, wo der Compiler prüfen kann, dass alle Möglichkeiten abgedeckt sind.
Beispiel
DayOfWeek today = LocalDate.now().getDayOfWeek();
System.out.println( switch ( today ) {
case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Arbeit";
case SATURDAY, SUNDAY -> "Party";
} );
Falls rechts neben dem Pfeil kein einfacher Ausdruck steht, sondern ein Block muss auch dieser Block ein Ergebnis zurückgeben. Dafür wird das neue Schlüsselwort yield eingesetzt, hinter dem ein Ausdruck kommt.
Beispiel
String operator = "+";
System.out.println( switch ( operator ) {
case "+" -> "Plus";
case "-" -> { String minus = "Minus"; yield minus; }
default -> throw new IllegalArgumentException( "Unknown operator" );
} );
Ein Block muss ein yield besitzen oder eine ungeprüfte Ausnahme auslösen.
Switch-Expression mit :-Syntax, mit Durchfall, vollständige Abdeckung
Auch die Doppelpunkt-Syntax lässt sich als Ausdruck einsetzten, mit ihr ist auch ein Durchfall wieder möglich; ein yield ist zwingend, oder eine ungeprüfte Ausnahme. Die Syntax birgt mit dem Durchfallen eine Fehlerquelle, sodass es vielleicht die schlechteste Variante ist.
Beispiel
String operator = "+";
System.out.println( switch ( operator ) {
case "+" : yield "Plus";
case "*" : System.out.println( "Sternchen" );
case "×" : yield "Mal";
default : throw new IllegalArgumentException( "Unknown operator" );
} );