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.
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.