28.7.2021 |

Java 16 - was ist neu? was ist anders?

Das im März erschiene OpenJDK 16 ist der letzte Major-Release vor der nächsten Long-Term-Support-Version (LTS) JDK 17, welches im September 2021 veröffentlicht werden soll. Dies ist vermutlich der Grund, wieso es weniger "brand-neue" Features gibt. Vielmehr wird versucht frühzeitiges Feedback durch die "zwischen"-Releases einzusammeln, um dieses dann für die nächste LTS Version zu finalisieren.

Die neuen alten Features:

  • 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)

Nachfolgend werden drei dieser Features kurz vorgestellt:

Pattern Matching

Was bereits mit JDK 12 begonnen wurde, wird nun mit JDK 16 beendet: Das Pattern Matching. Das Patten Matching versucht Objekte zu destrukturieren. Es versucht sie so aufzusplittern, das die einzelnen Elemente in verschiedenen Variablen zu gewiesen werden können um sie dann weiter zu verarbeiten. Wenn ein Object o vom Typ String oder vom Typ Collection ist, dann kann direkt mit den neuen Variablen (s und c) mit den entsprechenden Datentypen weitergearbeitet werden. Erzwungene Typumwandlungen sind nicht mehr nötig und werden stattdessen implizit durchgeführt. Dies vermeidet Redundanzen und ist Lesbarer.

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

Versiegelte Klassen

Sealed Classes wurden in Java 15 als Previewfeature eingeführt und verbleiben als JEP 397 auch im JDK 16 im Vorschaumodus. Voraussichtlich werden sie mit der Open JDK 17 finalisiert. Ganz konkret soll das Feature bei der Analyse von Mustern unterstützen. Als Entwickler war es bisher nur durch Zugriffsmodifikatoren (private, protected und public) möglich, die Ableitung von Klassen zu beschränken oder durch das Schlüsselwort final die Ableitung durch den Compiler komplett zu untersagen. Durch Sealed Classes gibt es nun einen deklarativen Weg, um gezielt bestimmten Subklassen die Ableitung zu erlauben.

public sealed class FeuerPokemon
  permits Glurak, Flamara, Lavados {
}

Die Klasse FeuerPokemon erlaubt die Ableitung nur den Klassen Glurak, Flamara, Lavados. Beziehungsweise sieht ein Entwickler sofort, welche Unterklassen es überhaupt gibt. Sealed Classes sind auch mit abstrakten Klassen möglich. Allerdings mit ein paar Einschränkungen. Eine Sealed Class und alle erlaubten Subklassen müssen im selben Modul vorhanden sein. Im Falle von Unnamed Modules müssen sie sogar im gleichen Package liegen. Desweiteren muss jede zulässige Subklasse direkt von der Sealed Class ableiten. Die abgeleiteten Klassen dürfen wiederum selbst entscheiden, ob sie weiterhin versiegelt, final oder für alle offen sein wollen. Die Versiegelung einer ganzen Klassenhierarchie von oben nach unten ist aber an zentraler Stelle nicht möglich.

Records

Bei Records handelt es sich um eine eingeschränkte Variante der Klassendeklaration, ähnlich den Enums. Sie sind im Umfeld der Einführung von Pattern Matching entstanden und werden in folgenden JDK-Releases noch relevanter werden. Ein Java-Record ist eine spezielle Art von Java-Klasse, die eine prägnante Syntax für die Definition von unveränderlichen (immutable) Klassen hat, die nur Daten enthalten. Java-Record-Instanzen können nützlich sein, um Datensätze zu speichern, die von einer Datenbankabfrage oder von einem Remote-Serivce-Aufruf zurückgegeben werden. Die einfache Definition einer Person mit zwei Feldern kann man nachfolgend betrachten:

public record Person(String name, Person partner ) {}

Eine erweiterte Variante mit einem zusätzlichen Konstruktor ist erlaubt. Dadurch lassen sich neben Pflichtfeldern auch optionale Felder abbilden:

public record Person(String name, Person partner ) {
  public Person(String name ) { 
    this( name, null ); 
  }
  public String getNameInUppercase() { 
    return name.toUpperCase(); 
  }
} 

Erzeugt wird vom Compiler eine unveränderbare (immutable) Klasse, die neben den beiden Attributen und den eigenen Methoden natürlich auch noch die Implementierungen für die Accessoren, den Konstruktor sowie equals/hashCode und toString enthält.

Hinweis: Vererbung funktioniert nicht bei Records!

Zur Übersicht
Patrick Schaper

Mehr vom Devsquad...

Sophia Brandt

Notizen zum Webinar "Grundlagen zeitgemäßer Architektur"

Sophia Brandt

Notizen zum Webinar "Moderne Web- und Cloud-Architektur"

Hallo

Wir sind für Sie da und freuen uns auf Ihre Fragen oder Ihr Feedback.