Neu in Java 14

29.03.2020 Tom Trapp
Tech Java JVM Good-to-know

Und wieder ist ein halbes Jahr vorbei und eine neue major JDK Version, namentlich JDK 14 ist im Anmarsch.

Was gibt es neues, was wurde ersetzt, verändert oder entfernt? Lasst es uns herausfinden!

Pattern matching instanceof

Das erste neue Feature ist das pattern matching für die the instanceof Functionalität.

Auf den ersten Blick würden Sie vielleicht denken, es handelt sich um ein pattern matching wie in einer Regex. Tatsächlich lassen sich mit pattern matching redundante Type-Castings bei einer einzeiligen Expression vermeiden.

Der traditionelle Weg, vor diese Feature würde wie folgt aussehen:

boolean isObjectNullOrEmpty(Object obj) {
    return obj == null ||
    (obj instanceof Collection && ((Collection) obj).isEmpty()) ||
    (obj instanceof String && ((String) obj).isBlank());
}

Dies ist eine simple methode isObjectNullOrEmpty() welche prüft, ob ein Objeckt, welches String oder Collection sein kann, null oder empty ist. Wäre es nicht elegant, könnte man das instanceof Prüfobjekt einer Inline-Variablen zu weisen? Genau das funktioniert nun:

boolean isNullOrEmpty(Object obj) {
    return o == null ||
    (obj instanceof Collection c && c.isEmpty()) ||
    (obj instanceof String s && s.isBlank());
}

Wir weisen das Objekt der Variablen c zu, wenn es sich um eine Collection handelt und führen anschliessend Checks direkt auf diesem bereits korrekt gecasteten Objekt aus. Selbstverständlich ist diese Methode null-safe, da wir einen locial and operator nutzen und somit die right side expression nur ausgeführt wird, wenn der erste Expression (left side) true zurückgibt.

Helpful NullPointerExceptions

Das nächste neue Feature, welches aktuell nur im Preview-State ist, sind hilfreiche NullPointerException.

Als Java Entwickler ist es wohl oder übel sehr wichtig, auf null Referenzen zu prüfen um Fehler zu vermeiden. Nichtsdestotrotz kennen Sie es sicher, dass gelegentlich Null Checks fehlen und es zu einer NullPointerException kommt. Vor dem Release von JDK 14 war es teilweise recht schwierig genau herauszufinden, woher der Fehler kommt und welche Variable genau null ist, speziell bei mehreren Expressions auf einer Zeile. Dieses neue Feature kann mit folgender JavaOption aktiviert werden:

XX:+ShowCodeDetailsInExceptionMessages

Beispielsweise würde der folgende Code eine detailliertere und Aussage über die NullPointerException geben:

women.partner().firstName()

java.lang.NullPointerException: Cannot invoke "Human.firstName()" because the return
value of "Human.partner()" is null

Somit ist klar ersichtlich, dass der Wert des Methodenaufrufs Human.partner null zurückgibt.

Neuer Datentyp - Records

Ein neue Datentyp mit Java 14? Richtig gelesen! Neu gibt es den sogenannten Record, dieser Typ ist auf den ersten Blick erstaunlich ähnlich zu einer Kotlin data class.

In der Vergangenheit hab es in Java Applikationen immer tonnenweise Data Classes, sogenannte Plain Old Java Objects. Diese Pojos beinhalteten meist simple Getter & Setter Methoden oder gar Lombok Annotations. Der Recordtype sollte diese Pojos ablösen, da er eine kompakte Syntax zum definieren solcher Data Klassen liefert. Beispielsweise würde die Human Klasse aus dem vorherigen Beispiel wie folgt aussehen:

public record Human( String firstName, String lastName, Person partner ) {}

Und das ist alles, was man braucht!

Der Compiler generiert eine immutable (!) Class mit dem Konstruktor, den final instance variables mit passenden Accessor Methods (leider keinen Getter Methods) und den Methoden hashcode, equals und toString.

public final class Human extends Record {
    private final String firstName;
    private final String lastName;
    private final Person partner;
    
    public Person(String firstName, String lastName, Person partner) { 
        this.fristName = fristName;
        this.lastName = lastName;
        this.partner = partner; 
    }
    
    public String toString() { /* ... */ }
    public final int hashCode() { /* ... */ }
    public final boolean equals(Object o) { /* ... */ }
    public String firstName() { return this.firstName; }
    public String lastName() { return this.lastName; }
    public Person partner() { return partner; }
}

Selbstverständlich kann der Record Type um andere static fields, Methoden oder einen anderen Konstruktor erweitert werden.

Leider ist dies nicht eine typische Java Bean, da die Klasse immutable ist und keine Getter Methoden beinhaltet. So können die Werte nach dem initialisieren des Objektes nicht mehr verändert werden und vorhandene Data Klassen müssen aufwendig migriert werden (Anpassung Getter -> Accessor Methods, Anpassung Business Logik da die Werte final sind).

Text Blocks

Wenn Sie die letzten major Java Versionen genauer verfolgt haben fragen Sie sich nun sicher, was es neue beim Feature Text Blocks gibt. Dieses Feature ist sozusagen der Nachfolger der Raw String Literals und erlaubt dem Entwickler das strukturierte definieren von mehrzeitligen Strings.

// Without Text Blocks
String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, old way</p>\n" +
              "    </body>\n" +
              "</html>\n";

// With Text Blocks
String html = """
              <html>
                 <body>
                    <p>Hello, new way with Text Blocks</p>
                 </body>
              </html>""";

Zusätzlich wurde in Java 14 ein alter Bekannter als Escape Sequence vorgestellt, der berühmte Backslash. Neu lassen sich so Strings auf mehreren Zeilen deklarieren, ohne unnötige Linebreaks im Output zu haben.

// Without Text Blocks
String literal = "Lorem ipsum dolor sit amet, consectetur adipiscing " +
                 "elit, sed do eiusmod tempor incididunt ut labore " +
                 "et dolore magna aliqua.";

//With Text Blocks
String text = """
                Lorem ipsum dolor sit amet, consectetur adipiscing \
                elit, sed do eiusmod tempor incididunt ut labore \
                et dolore magna aliqua.\
                """;

What else?

Schaut man nur auf den reinen Syntax der Programmiersprache ist das mehr oder weniger alles, was mir Java 14 verändert oder vorgestellt wurde.

Selbstverständlich hat sich auf "under the hood" viel mit Java 14 verändert, hier kurz die wichtigsten Changes:

  • Die FileChannel API wurde erweitert, um mit dem MappedByteBuffer arbeiten zu können. Dies ist aktuell nur auf GNU/Linux möglich.
  • Der Concurrent Mark Sweep (CMS) Garbage Collector wurde komplett entfernt, der ZGC ist nun auf Windows und macOS verfügbar.

Mit dem neuen halbjährigen Releasezyklus setzt Java auf ein leicht anderes Konzept. So sind Features früher als Preview-Features verfügbar, können ausgetestet werden und das Feedback der Community kann besser einfliessen. So können die Features wachsen bis zur nächsten Long Term Version, welche voraussichtlich Java 17 (Herbst 2021) sein wird.

Besuchen Sie uns regelmässig um über die neusten Changes informiert zu werden!

Tom Trapp – Problemlöser, Innovator, Sportler. Am liebsten feilt Tom den ganzen Tag an der moderner Software und legt viel Wert auf objektiv sauberen, leanen Code.