Aus Linux-Magazin 06/2020

Details zum neuen Java 14

© epicstockmedia, 123RF

Mit größeren und kleineren Verbesserungen vom neuen Record-Typen bis hin zum Feinschliff an der Speicherverwaltung will Java 14 weiter auf der seit 1996 anhaltenden Erfolgswelle surfen.

Dem sechsmonatigen Release-Zyklus folgend wurde die Arbeit an Java 14 Mitte März 2020 beendet, es steht nun zum Download bereit [1]. Die 14. Ausgabe erscheint genau zwischen den beiden Long-Term-Support-Versionen 11 und 17 und bietet damit genügend Spielraum für Veränderungen. Die sollen unter anderem dafür sorgen, Java weiterhin auf dem Treppchen der beliebtesten Programmiersprachen zu halten.

Generell bringt auch diese Version sowohl Änderungen mit, deren Entwicklung abgeschlossen ist, als auch solche, die lediglich vorläufig in Java landen. So wurde das erweiterte Switch-Statement zum Beispiel als Preview-Feature mit Java 12 eingeführt; Java 14 schließt die Entwicklung ab, sodass es nun ohne Kunstgriffe bereitsteht. Die Preview-Features lassen sich hingegen nur dann begutachten, wenn der Tester beim Kompilieren und Starten die Option »–enable-preview« und den Codelevel 14 angibt [2].

Record-Versuch

Die auffälligste Änderung stellt sicherlich der als Preview-Feature eingeführte Record dar. Dabei handelt es sich immerhin um die erste Ergänzung an Javas Typsystem seit 2004; damals führte Java 5 »enum« ein. Ein Record stellt ein abgeschlossenes Objekt in extrem kurzer Schreibweise bereit.

Die bisher genutzten POJOs (Plain Old Java Objects) enthalten in der Regel neben den Attributen noch Tonnen von Standardcode für Getter- und Setter-Methoden, »equals()«, »hashCode()«, »toString()« und so weiter. Die dabei benötigte Codemenge steht schon länger in der Kritik. Gerade für Datentransportobjekte ohne eigene Funktion braucht ein Entwickler eigentlich nur die Möglichkeit, eine Reihe von Attributen durchzureichen.

Wie Listing 1 zeigt, gelingt dies mithilfe der Records auf sehr knappem Raum. Es genügt, Namen und Attribute anzugeben. Die Objekte bieten dann den Zugriff auf die Variablen sowie die Methoden »hashCode()«, »equals()« und »toString()«, ohne sie implementieren zu müssen. Dabei sind die Variablen »immutable«: Der Entwickler darf sie nach der Zuweisung im Konstruktor nicht mehr ändern.

Listing 1

Preview-Features: Record-Typ und Textblock

public record Single( String name, String künstler, List<String> titel, int auflage ) {}
var bsp = new Single( "Substitute",
  "Gloria Gaynor",
  Arrays.asList( new String[]{ "Substitute", "I will survive" } ),
  1_400_000 );
var name = bsp.name();
System.out.println( "Single :" + bsp.toString() );
// Textblöcke
String alt ="Ein\n"+
            "mehrzeiliger\n"+
            "Text.";
String neu = """
             Ein
                mehrzeiliger
             Text.""";

Die Neuerung eignet sich perfekt für einen eher funktionalen Programmierstil und funktioniert hervorragend für Rückgabewerte aus Lambdas oder Methoden. Bei Bedarf definiert der Programmierer im Record weitere Methoden oder statische Variablen, was einen fließenden Übergang zu den POJOs ermöglicht.

Etwas unklar bleibt, wann ein Entwickler besser zu Records und wann zu Klassen greift. Hier müssen sich noch Best Practices etablieren. Für die nächsten Java-Versionen ist noch einiges an Bewegung rund um die Records zu erwarten, zum Beispiel im Zusammenhang mit Datenbankzugriffen.

Textblöcke

Schon als zweites Preview liegen die Textblöcke vor. Sie erlauben den Einsatz mehrzeiliger Textfragmente im Java-Code. C# und Python bieten hier schon lange eine Lösung. In Java klappte das bisher bestenfalls über ein hässliches Konstrukt aus Verkettungen von Strings und Zeilenumbrüchen (Listing 1, ab Zeile 12).

Dank der neuen Textblöcke sind solche Kunstgriffe nicht mehr nötig. Drei Anführungszeichen (»”””«) und ein Zeilenumbruch leiten einen Textblock ein (Listing 1, ab Zeile 16), drei weitere Anführungszeichen markieren das Ende des Blocks. Die einzelnen Textblöcke lassen sich dabei ganz wie normaler Code einrücken. Die sich dadurch ergebenden Leerzeichen an den Zeilenanfängen entfernt Java automatisch. Die Programmiersprache orientiert sich bei diesem Vorgang an der Position der schließenden An­führungszeichen (Abbildung 1).

<a href="#artRef-f1">Abbildung 1</a>: Die gesammelten Ausgaben der im Artikel gezeigten Listings.

Abbildung 1: Die gesammelten Ausgaben der im Artikel gezeigten Listings.

Switch beim Switch

Der erweiterte Switch-Ausdruck hat mit Java 14 hingegen die Preview-Phase verlassen. Bis Java 11 schleppte er eins zu eins die Syntax und die Macken aus dem C-Urahn mit sich herum, inklusive vergessener Fallthroughs oder Fallbehandlungen. Ziel des Updates war es, den Ausdruck durch den Verzicht auf den Fallthrough sicherer und mit Mehrfachoptionen sowie Rückgabewert mächtiger zu gestalten.

Listing 2 demonstriert die altbekannte Form sowie die beiden neueren Varianten. Je nach persönlichem Geschmack gibt es dafür die im Listing mit Variante 1 und Variante 2 bezeichnete Schreibweise.

Listing 2

Altes und neues switch-Statement

var test = "D";
// Altes Switch-Statement im C-Stil
String fall = "";
switch (test) {
  case "A":
    fall = "Fall 1";
    break;
  case "B":
  case "C":
    fall = "Fall 2";
    break;
  case "D":
    fall = "Fall 3"; // Fallthrough-Fehler, wird 'Fall 4'
  case "E":
    fall = "Fall 4";
    break;
  default:
    fall = "Fall 5";
}
System.out.format("C-Stil, für %1$s gilt %2$s\n", test, fall);
// Neuer Stil (Variante 1) mit ->
switch (test) {
  case "A" -> System.out.println("Stil I: Fall 1");
  case "B", "C" -> System.out.println("Stil I: Fall 2");
  case "D" -> System.out.println("Stil I: Fall 3");
  case "E" -> System.out.println("Stil I: Fall 4");
  default -> System.out.println("Stil I: Fall 5");
}
fall = switch (test) {
  case "A" -> "Fall 1";
  case "B", "C" -> "Fall 2";
  case "D" -> "Fall 3";
  case "E" -> "Fall 4";
  default -> Long.toString(test.length());
};
System.out.format("Variante 1, Rückgabe für %1$s ist %2$s\n", test, fall);
// Neuer Stil (Variante 2), mit Doppelpunkt und yield
var fall2 = switch (test) {
  case "A":
    System.out.println("Code hier ");
    yield "Fall 1";
  case "B":
  case "C":
    yield "Fall 2";
  case "D":
    yield "Fall 3";
  case "E":
    yield "Fall 4";
  default:
    yield "Fall 5";
};
System.out.format("Variante 2, für %1$s gilt %2$s\n", test, fall2);

Im ersten Fall kommt der aus den Lambdas bekannte Pfeil »->« zwischen Werten und Aktion zum Einsatz. Er ermöglicht mehrere Fälle per »case« und verursacht keinen Fallthrough mehr. Wie Zeile 32 zeigt, weist der Entwickler mit derselben Schreibweise auch gleich eine Variable zu.

Für Traditionalisten steht die alte Schreibweise mit Doppelpunkt zur Verfügung. Hier ermöglicht der Einsatz von »yield« statt »break« die Rückgabe von Werten, wobei die Gefahr ungewollter Fallthroughs bleibt.

Auch an anderen Stellen gibt es kleinere Detailverbesserungen. Die Typprüfung mit »instanceof« vermag nebenläufig eine typsichere Variable zuzuweisen, was eine Extrazeile mit dem Cast erspart. Listing 3 zeigt sowohl die alte als auch die neue Schreibweise.

Listing 3

Preview-Feature instanceof mit Variable

Object obj = "Ich bin ein String";
// alte Schreibweise
if ( obj instanceof  String  && ((String)obj).length() >2 ) {
  String nunAber = (String) obj;
  System.out.println("String " + nunAber);
}
// neue Schreibweise
if ( obj instanceof String svar && svar.length() > 2) {
  System.out.println("String " + svar);
}

Handelt es sich beim Objekt in der Variablen »obj« um einen String, weist die neue Schreibweise es als Seiteneffekt der finalen Variablen »svar« zu. So lässt es sich ohne weitere Casts einsetzen.

Eine weitere Änderung heißt sinnigerweise Helpful NullPointerExceptions, denn hilfreich sind NullPointerExceptions bislang oft nicht. Treten sie auf, erhalten Entwickler lediglich die Information, dass sie auftraten, nicht aber wo. Wer Java 14 mit dem Flag »-XX:+ShowCodeDetailsInExceptionMessages« startet, erhält nun die Information, welche Variable »null« war:

Cannot invoke "String.length()" because "leererName" is null

Weniger sichtbar fallen die weiteren Änderungen an der Laufzeitumgebung aus. Hier lassen sich etwa Dateien aus nicht flüchtigem Speicher direkt als »MappedByteBuffer« nutzen. Der Flight Recorder beherrscht wieder mehr Funktionen, und es gab weitere Verbesserungen an den Garbage-Kollektoren.

An Desktop-Anwender und solche mit mobilen Geräten richtet sich dagegen das moderne UI-Framework JavaFX [3]. Seit Java 11 gehört es nicht mehr zur JDK-Basis, das Unternehmen Gluon entwickelt es federführend separat weiter. In Version 14 von JavaFX haben die Entwickler neben diversen Bugfixes die genutzten abhängigen Teile wie Gstreamer, GTK oder Mesa auf den aktuellen Stand gehoben. Passend dazu gibt es im Samples Project [4] auch wieder Startprojekte für verschiedene Entwicklungsumgebungen und Build-Tools.

Fazit

Es stellt sich abschließend die Frage, wie und ob Anwender und Entwickler Java 14 nutzen sollen. Das Wie ist kein Problem, denn viele wesentliche Entwicklungsumgebungen – darunter NetBeans, IntelliJ und Eclipse – unterstützen Java 14 bereits und meckern auch nicht beim Einsatz von Previews. Lediglich die automatische Codeformatierung lässt Vorsicht geboten erscheinen: Für die Grammatik einiger Preview-Features fehlt noch der Support.

Bleibt die Frage nach dem Ob. Der konsequente Einsatz der neuen Syntax stellt keinen so großen Schritt dar wie die Einführung der Lambdas, erspart dem Programmierer aber einiges an Tipparbeit. Dennoch dürften viele Entwickler, die produktiven Code schreiben, wohl eher abwarten, bis mit Java 17 das nächste Langzeit-Release erscheint. (kki/jlu)

Der Autor

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

Infos

  1. Adopt OpenJDK: https://adoptopenjdk.net

  2. Preview-Features: https://openjdk.java.net/jeps/12

  3. JavaFX 14: https://openjfx.io

  4. JavaFX Samples: https://github.com/openjfx/samples

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 3 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