Neues aus der Java-Welt, eine neue Version des Java Development Kits (JDK) ist da, nämlich JDK 21!
Auf folgende Fragen wollen wir in diesem TechUp eingehen:
- Was kam Neues mit JDK 21? ❓
- Collections mit Reihenfolge? 🚀
- String Templating ganz anders? 🤔
- static void final whatever main(Something in here) {}? 🤯
- Virtual Threading mit Java? 🤔
JDK 21
JDK 21 ist die letzte LTS (Long Term Support) Version von Java. Diese Version wurde im September 2023 veröffentlicht. Schauen wir uns die wichtigsten Features und Verbesserungen an.
Also starten wir!
Zuerst, nach einer gefühlten Ewigkeit, bis endlich brew upgrade
durchgelaufen ist, habe ich die JDK 21 von Temurin für mein MacBook installiert.
Übrigens, alle Codebeispiele findet ihr als komplettes Projekte hier im b-nova-techhub/java-21 Repository.
Kleiner Tipp am Rande: Für die komplette Nerd-Experience schaut mal bei https://javaalmanac.io/ vorbei. 🚀
String Templates (Preview)
JEP 430: String Templates (Preview)
Wer die letzten Java Releases verfolgt hat, denkt sicher sofort “schon wieder String Templates oder Interpolations?”. In den letzten Versionen ging es oft um mehrzeilige String, nun geht es konkret darum, dynamische Bereiche in einem String einfacher und schöner definieren zu können.
Schauen wir uns an, wie man das vorher gemacht hätte:
|
|
Wir sehen drei unterschiedliche Möglichkeiten, welche in der Vergangenheit sicher zahlreich genutzt wurden.
Neu gibt es sogenannte StringTemplates
, welches uns eine Placeholder-Logik mittels der \{}
Syntax bereitstellen.
Die neue Lösung würde wie folgt aussehen:
|
|
Schauen wir uns noch weitere Beispiele an!
|
|
Zu sehen ist, wie wir sehr einfach über ein Placeholder oder gar Templating-Syntax Strings dynamisch generieren können. Ebenfalls lassen sich Methodenaufrufe und Berechnungen direkt in den String einbauen.
Neben STR
gibt es auch noch FMT
für bestimmte Formatting und RAW
um das eigentliche StringTemplate einmalig zu definieren und mittels einer process
Methode dann aufzurufen.
Die Möglichkeiten in Zukunft sind hier sicher gigantisch, da sehr einfach eigene Processors geschrieben werden können:
|
|
|
|
Hier ist schön zu sehen, dass wir nicht nur Variablen im StringTemplate nutzen können, sondern auch Methoden aufrufen können oder beispielsweise Berechnungen durchführen können.
Sequenced Collections
JEP 431: Sequenced Collections
Eine weitere Neuerung, welche mit JDK 21 als stable Feature dazu kam, sind die sogenannten “Sequenced Collections”.
So ist es neu möglich, beispielsweise das erste oder das letzte Element einer Collection zu erhalten. Und das nicht wie in der Vergangenheit über get(0)
oder get(size()-1)
, sondern über die neuen Methoden getFirst()
und getLast()
.
Selbstverständlich funktioniert dies nur, wenn die Implementation der Collection dies auch unterstützt, indem das Interface SequencedCollection
implementiert ist.
Im nachfolgenden Codeausschnitt ist zu lesen, dass wir sowohl mit getFirst()
und getLast()
lesen als auch mit addFirst()
und addLast()
schreiben können.
|
|
Ausserdem bietet das Interface auch die Methoden removeFirst()
und removeLast()
an.
Zu beachten ist, dass die schreibenden Methoden wie add*
und remove*
nur dann funktionieren, wenn die Collection dies auch unterstützt.
Sollte es sich um eine ImmutableCollection handeln, so wird eine UnsupportedOperationException
geworfen.
Schauen wir uns kurz das überarbeitete Klassendiagramm an!
Sofort fällt auf, dass das wahrscheinlich am meisten genutzte Interface List
neu das Interface SequencedCollection
implementiert.
Das bedeutet, unser Code muss in den meisten Fällen nicht angepasst werden und wir haben direkt Zugriff auf die neuen Methoden.
Source: https://openjdk.org/jeps/431
Zu sehen ist auch, dass es die analoge Implementation auch als SequencedSet
und als SequencedMap
gibt.
Die neue Main Methode
JEP 445: Unnamed Classes and Instance Main Methods (Preview)
Festhalten, Anschnallen, Los geht’s! 👨🏻🚀
Mit dem Preview-Feature JEP 445: Unnamed Classes and Instance Main Methods (Preview) kommt im inzwischen 65. Release von Java DIE! bahnbrechende Neuerung.
Neu gibt es sogenannte “unbenannte Klassen” und “Instanz-Main-Methoden”. Das bedeutet, dass wir die Main-Methode nicht mehr in einer Klasse definieren müssen, sondern einfach direkt geschrieben werden kann.
Wenn ich mich zurückerinnere an meine Java Anfänge vor 12 Jahren, immer diese Auswendiglernerei von public static void main(String[] args)
, das ist jetzt Geschichte!
|
|
Das ist eine klassische Java-Klasse mit einer main Methode, sicher jeder Java-Neuling beginnt mit so einer Klasse. Aber das ist jetzt Schnee von gestern.
|
|
Und das ist alles! Keine Klasse, kein package, keine komplizierten Parameter einfach nur eine main
Methode, wie man es aus anderen Sprachen kennt.
Gestartet wird das Programm wie gewohnt!
Hands-down, das ist wirklich eine gelungene Neuerung für Java. Dies erleichtert den Einstieg und macht die Sprache zugänglicher, aber auch für erfahrene Entwickler ist das eine willkommene Neuerung, wenn man schnell mal ein paar Zeilen Code testen möchte.
Das Konzept der unnamed Klasse ist nicht gänzlich neu, in vergangenen Versionen gab es auch schon unnamed Module und unnamed Packages.
Hier ist noch spannend zu erwähnen, dass man euch mehrere main
Methoden mit unterschiedlichen Parametern definieren kann. Das ist ein weiterer Schritt in Richtung Flexibilität und Einfachheit.
In diesem Fall entscheidet dann ein entsprechendes Launch-Protocol, welche main
Methode aufgerufen wird.
Virtual Threading
Last but not least, sicherlich das wichtigste Features des JDK 21 Release, die virtual Threads!
Nehmen wir an, wir haben eine API, welche wir abfragen müssen, jeder API Call dauert eine Sekunde.
|
|
Wir haben eine lange Liste von Objekten, welche wir mit Daten aus der API anreichern müssen. Die API hat genug Power, also können wir parallel Arbeiten, um die Daten schneller zu erhalten.
Bis jetzt haben wir das mit Thread
oder ExecutorService
gemacht, aber das ist nicht wirklich effizient, da die Threads zu viel Overhead haben.
|
|
In dem Codeausschnitt haben wir 100 Objekte, für jedes Objekt starten wir einen “echten” Thread, welcher die API abfragt. Die Ausführung dieses Programmes dauert im Schnitt 1100 Millisekunden. (Und wir nutzen String Templates, cool! 🚀)
Schauen wir uns nun das gleiche Beispiel mit virtual Threads an:
|
|
Viel geändert hat sich nicht, das Programm läuft auch um die 1100 Millisekunden, aber der Unterschied ist, dass wir keine “echten” Threads mehr verwenden, sondern “virtuelle” Threads.
Mittels eines Diffs ist einfach zu sehen, was die effektiven Änderungen sind:
Es ist also sehr einfach, aus einem echten auf einen virtuellen Thread zu wechseln.
Nun aber @Scale! Was passiert, wenn wir plötzlich 100'000 Objekte haben? Also passen wir die Nummer in der Schleife an und starten das Programm neu.
Die alte Lösung läuft: 19222 Millisekunden, was knapp 20 Sekunden entspricht. Recht lange! 😴
Die neue Lösung mit virtual Threads läuft: 1722 Millisekunden, was knapp 2 Sekunden entspricht. Das ist ein riesiger Unterschied!
Denken wir das nun weiter, wenn wir beispielweise einen Webserver haben, welcher Millionen von Anfragen pro Sekunde verarbeiten muss, dann ist das ein riesiger Unterschied. Oder ist das nur in der Theorie?
Zahlreiche Benchmarks im Internet zeigen, dass die virtual Threads bis zu einem gewissen Punkt deutlich schneller sind. Ab diesem Punkt performen die virtual Threads gleich gut oder sogar schlechter als die “echten” Threads. Weitere Informationen findet ihr hier.
Sicher stellt sich hier die Frage, wie in Zukunft Java Applikationen aufgebaut werden, klassische sequentiell oder mit echten Thread, nach dem Reactive Programming Prinzip oder mit virtuellen Thread?
Diese Frage ist schwer zu beantworten, da es sehr stark von der Applikation und den Anforderungen abhängt.
Wir werden in Zukunft die virtual Threads im Auge behalten und sicherlich bei dem einen oder anderen Quarkus Projekt mittels RunOnVirtualThread
experimentieren.
Wenn du an diesem Punkt mehr über virtual Threads erfahren willst, dann lege ich dir diesen Quarkus Artikel ans Herzen!
Varia
Kurz notiert:
Mittels Math.clamp() können wir neu prüfen, ob ein Wert innerhalb eines bestimmten Bereichs liegt. Ist der Wert ausserhalb, wird der entsprechende Min- oder Max-Wert zurückgegeben. Das könnte ganz praktisch sein!
|
|
Ausserdem hat sich wieder, wie die letzten Releases etwas an den Switch Statements getan, dort kann man nun direkt ein Pattern-Matching ohne lästige instanceof Checks implementieren. Zusätzlich gibt es neu auch weitere Matching Möglichkeiten für Record Types.
LTS
Hier sei nochmals erwähnt, dass es sich um eine LTS Version handelt, welche länger als die normalen Releases unterstützt wird.
Aus meiner Sicht lohnt sich der Wechsel! Die komplette Liste aller JEPs vom Sprung von der letzten LTS-Version Java 17 auf JDK 21 findet ihr hier.
Fazit
Coole und wirklich praktische Features wurden uns mit JDK 21 beschert! Die virtual Threads werden sicherlich die Performance von Webservern oder gar generell Application Servern deutlich verbessern! Sequenced Collections und String Templates sind sicherlich Features, die wir in Zukunft sehr oft nutzen werden.
Ausblick
Java 22 steht bereits in den Startlöchern und soll im März 2024 veröffentlicht werden. Aktuell sind schon einige Features bekannt, die wichtigsten und coolsten Features schauen wir uns im nächsten TechUp an! 🚀 JDK 23 ist auch schon in Planung und es gibt schon einige spannende Features, die uns Entwickler erwarten.