Neuerungen in der Java SE: Eine kurze «case» Study

switch, case, default und break – JAVA-Experte Dominic A. Merz zeigt uns in diesem Artikel, welche Möglichkeiten mit den Neuerungen sich für die Programmierung mit JAVA eröffnen.

Autor Dominic A. Merz
Datum 22.01.2020
Lesezeit 4 Minuten

Was haben wir uns doch in der Praxis und bei Examen schon den Kopf zerbrochen, wie die Schlüsselwörter switch, case, default und break bei einer Fallunterscheidung richtig zu verwenden sind!

Insbesondere der mögliche Datentyp der Variablen im switch(), die Art der Konstanten in den case-Zweigen, der Ort eines default-Zweigs und das Weglassen der break-Anweisung, bewusst (als sog. Fall Through) oder unbewusst (als Fehler), können uns bei dieser Kontrollstruktur doch des öfteren irritieren.

Auf jeden Fall sind zwei Sachen sicher:

  • Eine Fallunterscheidung mit einer switch()/case/default-Anweisung ist gewöhnlicherweise performanter als eine entsprechende Mehrfachauswahl mittels if()/else if()/else.
  • Die Struktur liefert mir immer wieder tolle Zertifizierungsfragen.

Schauen wir uns zuerst die traditionelle Verwendung anhand eines Beispiels an (vgl. Listing 001 und Console 001), das uns für ein gewöhnliches Jahr zum englischen Namen eines Monats die Anzahl seiner Tage liefert und am Standard Output ausdruckt. (Ja, für das Jahr 2020 geht das so nicht. Ja, mit dem Date/Time API der Java SE 8 geht das viel einfacher.)

Listing 001

001 package example;
002
003 public class Application {
004
005     public static void main(String args) {
006         String nameOfMonth = args0;
007         int numberOfDays;
008         switch (nameOfMonth) {
009         default:
010             numberOfDays = 0;
011             break;
012         case "February":
013             numberOfDays = 28;
014             break;
015         case "April":
016         case "June":
017         case "September":
018         case "November":
019             numberOfDays = 30;
020             break;
021         case "January":
022         case "March":
023         case "Mai":
024         case "July":
025         case "August":
026         case "October":
027         case "December":
028             numberOfDays = 31;
029             break;
030         }
031         System.out.printf("%d days.%n", numberOfDays);
032     }
033 }

Console 001

>javac example\Application.java
>java example.Application January
31 days.
>

Das JEP 325 im JDK 12 und das JEP 354 im JDK 13 stellt uns nun als Preview eine Reihe von Anpassungen und Verbesserungen vor, die uns die Verwendung einer Fallunterscheidung erleichtern sollen. (Die endgültige Version fliesst wohl mit dem JEP 361 in das JDK 14 ein.)

So können wir jetzt z.B. mehrere case-Zweige zusammenfassen, indem wir die entsprechenden Werte mittels einer kommagetrennten Liste aufzählen (vgl. Listing 002 und Console 002).

Listing 002

001 package example;
002
003 public class Application {
004
005     public static void main(String args) {
006         String nameOfMonth = args0;
007         int numberOfDays;
008         switch (nameOfMonth) {
009         default:
010             numberOfDays = 0;
011             break;
012         case "February":
013             numberOfDays = 28;
014             break;
015         case "April", "June", "September", "November":
016             numberOfDays = 30;
017             break;
018         case "January", "March", "Mai", "July", "August", "October",
019                 "December":
020             numberOfDays = 31;
021             break;
022         }
023         System.out.printf("%d days.%n", numberOfDays);
024     }
025 }

Console 002

>javac --enable-preview --source 13 example\Application.java
>java –enable-preview example.Application January
31 days.
>

Des weiteren ist es uns neu möglich, eine Fallunterscheidung nicht nur als Anweisung, sondern auch als Ausdruck zu verwenden – z.B. in einer kompakten Zuweisung, siehe dazu Listing 003 und Console 003. (Wer fühlt sich da nicht an die kompakte Alternativstruktur mit dem ternären Bedingungsoperator ?: erinnert?)

Dabei geben wir nach dem neuen Schlüsselwort yield einfach flink den ausgewählten Rückgabewert an und schliessen die Zuweisung selbstverständlich nach dem ganzen Block mit einem Semikolon ab (vgl. Listing 003, Linie 017).

Listing 003

001 package example;
002
003 public class Application {
004
005     public static void main(String args) {
006         String nameOfMonth = args0;
007         int numberOfDays = switch (nameOfMonth) {
008         default:
009             yield 0;
010         case "February":
011             yield 28;
012         case "April", "June", "September", "November":
013             yield 30;
014         case "January", "March", "Mai", "July", "August", "October",
015                 "December":
016             yield 31;
017         };
018         System.out.printf("%d days.%n", numberOfDays);
019     }
020 }

Console 003

>javac --enable-preview --source 13 example\Application.java
>java –enable-preview example.Application January
31 days.
>

Die Neuerungen vereinfachen uns eine Fallunterscheidung und kürzen zumindest den nötigen Programmcode. Ausserdem versehen sie uns auch mit einem klareren Kontrollfluss, indem sie z.T. ein Fall Through oder ein vergessenes break erst gar nicht mehr zulassen.

Und immer noch sind zwei Sachen sicher:

  • Es gilt «Chamer mache, muemer aber nööd.» – wie wir im Kollegenkreis oft zu sagen pflegen.
  • Die neue Struktur liefert mir vermehrt tolle Zertifizierungsfragen.

Über den Autor

Dominic A. Merz

Seit seiner Studienzeit beschäftigt sich Dominic A. Merz mit der Syntax von Sprachen, der Objektorientierung, der Softwarearchitektur sowie den verschiedenen Technologien in Zusammenhang mit Java, XML und dem Web. Als von Oracle zertifizierter Trainer unterrichtet er bei Digicomp vorwiegend in öffentlichen Tageskursen, Firmenkursen sowie Zertifizierungslehrgängen.