Aus Linux-Magazin 06/2019

Neu in Java 12

© mihalec, 123RF

Das Switch-Statement erhält ein dringend nötiges Update, und Tee reicht Java 12 jetzt auch als Streaming-Funktion: Seit Ende März 2019 steht die zwölfte Ausgabe der Programmiersprache bereit.

Mit Java 12 schafft es Mark Reinhold das dritte Mal in Folge, eine Java-Release pünktlich vom Hof zu schaffen [1]. Nach dem als Longterm-Support-Release geadelten Vorgänger Java 11 handelt es sich nun um eine Feature-Release, die keine umwälzenden Neuerungen an Sprache oder Lizenzpolitik mit sich bringt.

Die wohl sichtbarste Änderung an Java 12: Die Entwickler haben das »switch«-Statement erweitert (Listing 1). Syntax wie Funktionsweise stammten seit Javas Anbeginn direkt aus C, was nicht alle Fans begeisterte.

Listing 1

Neuerungen für Switch

01 String var = "D";
02   // Switch im C-Stil
03   switch (var) {
04       case "A":  System.out.println("C: A"); break;
05       case "B":
06       case "C":  System.out.println("C: B oder C"); break;
07       case "D":  System.out.println("C: D"); // Fall-Through-Fehler
08       case "E":  System.out.println("C: E"); break;
09       default:   System.out.println("C: Sonstiges");
10   }
11
12   // Neue Stil I, Mehrfachtreffer
13   switch (var) {
14       case "A":    System.out.println("M: A"); break;
15       case "B", "C": System.out.println("M: B oder C"); break;
16       case "D":    System.out.println("M: D"); // Fall-Through-Fehler
17       case "E":    System.out.println("M: E"); break;
18       default:     System.out.println("M: Sonstiges");
19   }
20   // Neue Stil II, kein Fall Through mehr
21   switch (var) {
22       case "A" ->    System.out.println("N: A");
23       case "B", "C" -> System.out.println("N: B oder C");
24       case "D" ->    System.out.println("N: D");
25       case "E" ->    System.out.println("N: E");
26       default ->     System.out.println("N: Sonstiges");
27   }

Zwar ist das Statement inzwischen nicht mehr nur auf Integer-Werte beschränkt, sondern kennt auch Enumerationen oder Strings. Aber ein wesentlicher Nachteil bleibt das gefährliche Fall-Through-Verhalten. Das macht das »switch«-Statement zu einem Spitzenkandidaten für Logikfehler. Ein vergessenes »break« – und schon übernimmt das Programm den Wert »D« in Zeile 7 gleich noch in Zeile 8.

Switch ließe sich als mächtiges Werkzeug nutzen, ist aber in den Styleguides einiger Firmen inzwischen ausdrücklich verboten, da im Umgang mit dem Statement zu viel zu Bruch ging. Seit Java 11 gibt es deshalb zwei Änderungen an der Grammatik, die den Code kürzer und sicherer machen sollen. So lassen sich wie in Zeile 15 gleich mehrere Gültigkeiten mit Kommas trennen. Noch sicherer ist die auch neu eingeführte Syntax mit dem »->« (Zeile 22). Mit ihr setzt der Compiler automatisch ein »break«-Statement ein. Der in Zeile 7 enthaltene Fehler passiert so nicht mehr, was die Gefahr von Logikfehlern deutlich verringert.

Abbildung 1: Die Ausgaben zu den drei Listings im Artikel.

Abbildung 1: Die Ausgaben zu den drei Listings im Artikel.

Das ist zwar kein umwälzendes Feature, kann aus Sicherheitserwägungen aber durchaus den Schritt von Java 11 nach Java 12 attraktiv machen. Aber Achtung: Entwickler dürfen die Syntax mit dem Doppelpunkt und dem Pfeil nicht in einem »switch«-Statement kombinieren. Zudem müssen sie die Option »–enable-preview« angeben (Abbildung 1).

Tee-Kränzchen

Neben der Sprachsyntax selbst entwickelt sich natürlich die Laufzeitbibliothek. Eine interessante Erweiterung fand im Umfeld der Streams statt. Die »teeing()«-Funktion ermöglicht es, Streams zu verzweigen und dann zusammenzuführen, wie es unter Linux der Befehl »tee« vermag. Wie Abbildung 2 zeigt, führt Java 12 den Stream dabei in zwei Kollektoren. Deren Ergebnis behandelt dann eine Funktion mit zwei Eingängen und stellt es als neuen Stream bereit.

Abbildung 2: Die »teeing()«-Funktion erlaubt es, einen Stream zu verzweigen und wieder zusammenzuführen.

Abbildung 2: Die »teeing()«-Funktion erlaubt es, einen Stream zu verzweigen und wieder zusammenzuführen.

Den Code dazu zeigt Listing 2. Konkret berechnet er das Verhältnis zwischen Minimal- und Maximaltemperatur. Die Temperaturwerte stehen in einem Stream bereit und werden dem Teeing-Operator zugeführt. Der nutzt die »minBy()«- und »maxBy()«-Funktionen als Kollektoren, beide geben jeweils ein »Optional<Double>« zurück.

Listing 2

Teeing

01 double ratio = Stream.of(6.1, 7.3, 7.5, 7.8, 9.8, 11.3, 11.4, 9.6, 8.6, 7.7).
02     collect(  // Ergebnis einsammeln
03       teeing( // Aufteilen
04         minBy(Double::compareTo), // Pfad 1: Minimum finden
05         maxBy(Double::compareTo), // Pfad 2: Maximum finden
06         (min, max) -> min.get() / max.get() // Join Operator
07       )
08     );
09   System.out.println("verhältniss min/max " + ratio);

Die Bifunktion (Zeile 6) bekommt die beiden Rückgabewerte als Eingabewert und berechnet das Verhältnis. Die »collect()«-Funktion in Zeile 2 dient dann nur noch dazu, das Ergebnis aus dem Ausgabestream der »teeing()«-Funktion aufzusammeln. Dank der Verzweigungsmöglichkeit lassen sich so viele Auswertungen einfacher schreiben.

Fescher formatieren

Für weitere Änderungen wie das Überspringen von Bytes aus einer Datei (»InputStream.skipNBytes«) dürfte sich vermutlich nur ein Teil der Java-Anwender begeistern. Für die tägliche Arbeit erweisen sich hingegen die Formatierungs-Erweiterungen als praktisch. Da wäre zum einen die Ausgabe von Zahlen in einem kompakten, menschenlesbaren Format.

Dank »getCompactNumberInstance()« in den Zeilen 3 und 4 von Listing 3 erzeugt Java 12 eine neue Formatierung. Deren Ausgabe im kurzen und langen Format demonstriert wieder Abbildung 1. Als ebenso praktisch könnte sich auch die neue »String.indent()«-Funktion erweisen (Zeile 12), bisher mussten Entwickler das immer selbst implementieren.

Listing 3

Schöner Einrücken

01   // Ausgaben
02   System.out.println("--- Ausgaben ---");
03   NumberFormat snf = NumberFormat.getCompactNumberInstance(Locale.GERMAN, NumberFormat.Style.SHORT);
04   NumberFormat lnf = NumberFormat.getCompactNumberInstance(Locale.GERMAN, NumberFormat.Style.LONG);
05   Stream.of(1e3, 1e6, 1e9).forEach( i-> {
06           System.out.println( snf.format(i) + ", " + lnf.format(i));
07       });
08
09   System.out.println("--- Einrückung ---");
10   Stream.of(-1, 0, 2, 4, 8).forEach( i-> {
11       String s = String.format("%d", i);
12       s = s.indent(i);
13       System.out.print( s);
14   });

Fazit

Zusammenfassend bringt Java 12 nach den großen Umwälzungen in Java 10 und 11 eher kleinere Änderungen mit sich. Das neue Switch-Statement, schönere Formatierungen sowie Teeing sind dabei wohl die wesentlichen Nachrichten. Die weiteren Verbesserungen am Garbage Collector sind nett, liefern aber kaum eine Motivation zum Umstieg auf die neueste Version.

Der Autor

Carsten Zerbst entwickelt mit seinem Team Individualsoftware für die Automobil-, Luft- und Raumfahrtindustrie sowie den Schiffbau. Er sucht zusätzliche Mitarbeiter für abwechslungsreiche Tätigkeiten mitten in Hamburg.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 2 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben