14, 15 oder doch schon 16? Da kann man schon mal durcheinanderkommen. Durch die mittlerweile halbjährlichen Major-Releases von Java fällt es gar nicht so leicht, die aktuelle Version richtig zu benennen. Vor Kurzem hat man sich in einem Vortrag noch über die Neuerungen des JDK 14 informiert, und wenig später wurden in einem Artikel bereits die Features von Version 15 näher beleuchtet. Und da sich die Welt bekanntlich schnell weiterdreht, ist nun im März 2021 bereits das OpenJDK 16 herausgekommen.
Um die Verwirrung komplettzumachen, kann man sich natürlich auch nur auf die sogenannten Long-Term-Support-Versionen (LTS) konzentrieren, die alle drei Jahre erscheinen. Das ist im Moment Java 11, wobei in der freien Wildbahn die Version 8 ebenfalls noch sehr weit verbreitet ist. Im September 2021 wird nun mit dem JDK 17 das nächste LTS-Release erscheinen. Dort werden die Neuerungen der vergangenen drei Jahre (Java 12 bis 16) finalisiert, um bis zur darauffolgenden LTS-Version (JDK 23) gut dazustehen. In den vergangenen „Zwischen“-Releases wurden die diversen, teilweise auch größeren Änderungen häufig als Previews veröffentlicht. Dadurch konnte frühzeitig Feedback eingesammelt und bereits im nächsten Release eingearbeitet werden.
(Nicht ganz so) neue Features
Die Liste der für das OpenJDK 16 umgesetzten JEPs (Java Enhancement Proposals) sieht auf den ersten Blick wieder relativ lang aus [1]:
338: Vector API (Incubator)
347: Enable C++14 Language Features
357: Migrate from Mercurial to Git
369: Migrate to GitHub
376: ZGC: Concurrent Thread-Stack Processing
380: Unix-Domain Socket Channels
386: Alpine Linux Port
387: Elastic Metaspace
388: Windows/AArch64 Port
389: Foreign Linker API (Incubator)
390: Warnings for Value-Based Classes
392: Packaging Tool
393: Foreign-Memory Access API (Third Incubator)
394: Pattern Matching for instanceof
395: Records
396: Strongly Encapsulate JDK Internals by Default
397: Sealed Classes (Second Preview)
Einige der Punkte sind für Java-Entwickler aber nicht direkt relevant. Dazu zählen beispielsweise die Migration zu Git/GitHub, die Aktivierung der C++-14-Sprachfeatures und auch das Foreign Linker API als zukünftiger Ersatz für das Java Native Interface (JNI). Wir schauen am Ende dieses Artikels trotzdem genauer darauf. Werfen wir aber zunächst einen Blick auf die Funktionen, die uns Entwickler betreffen. Dabei werden dem aufmerksamen Beobachter der vergangenen Java-Releases allerdings keine bahnbrechenden Neuerungen ins Auge springen. Das hängt vermutlich mit dem bevorstehenden LTS-Release zusammen, das im Herbst 2021 erscheinen wird. In Java 17 werden die neuen Features der vergangenen Monate stabilisiert, um für die folgenden Jahre eine gute Ausgangsbasis für die notwendigen Updates und Patches zu schaffen.
Java goes Pattern Matching
Bereits seit einiger Zeit schwebt das Thema Pattern Matching im Raum und hält nach und nach Einzug in Java. Dazu sind aber zur Vorbereitung diverse Änderungen in der Sprache selbst notwendig und deshalb erfolgt die Einführung nur schrittweise. Los ging es mit den Switch Expressions bereits im JDK 12. Seit Version 14 gab es zudem bereits zwei Previews zu „Pattern Matching for instanceof“. Das wird nun mit Java 16 abgeschlossen.
Ein Pattern ist übrigens eine Kombination aus einem Prädikat (das auf eine Zielstruktur passt) und einer Menge von Variablen innerhalb dieses Musters. Diesen Variablen werden bei passenden Treffern die entsprechenden Inhalte zugewiesen und damit extrahiert. Die Intention des Pattern Matching ist letztlich die Destrukturierung von Objekten, also das Aufspalten in die Bestandteile und Zuweisen in einzelne Variablen zur weiteren Bearbeitung. Die Spezialform des Pattern Matching beim instanceof-Operator spart unnötige Casts auf die zu prüfenden Zieldatentypen. Wenn o ein String oder eine Collection ist, dann kann direkt mit den neuen Variablen (s und c) mit den entsprechenden Datentypen weitergearbeitet werden. Das Ziel ist es, Redundanzen zu vermeiden und dadurch die Lesbarkeit zu erhöhen (Listing 1).
Listing 1
boolean isNullOrEmpty( Object o ) { return o == null || o instanceof String s && s.isBlank() || o instanceof Collection c && c.isEmpty(); }
Der Unterschied zum zusätzlichen Cast mag marginal erscheinen. Für die Puristen unter den Java-Entwicklern spart das allerdings eine kleine, aber dennoch lästige Redundanz ein. Laut Brian Goetz soll die Sprache dadurch prägnanter und die Verwendung sicherer gemacht werden. Erzwungene Typumwandlungen werden vermieden und stattdessen implizit durchgeführt. Bereits die zweite Preview, die im JDK 15 erschienen war, hatte keine nennenswerten Änderungen mehr mit sich gebracht. Deswegen wird das Feature jetzt als JEP 394 finalisiert. In zukünftigen Java-Versionen wird es aber noch weitere Funktionen rund um das Pattern Matching geben, zum Beispiel in Zusammenarbeit mit den Switch Expressions.
Versiegelte Klassen
Erst das zweite Mal dabei sind die Sealed Classes. Sie wurden in Java 15 als Previewfeature eingeführt und verbleiben als JEP 397 auch im JDK 16 im Vorschaumodus. Es gibt ein paar kleine Ergänzungen ...