© GreenFlash/Shutterstock.com
Von Version zu Version – Teil 2

Datenspeicher neu gedacht


Nachdem wir uns in der vorigen Ausgabe einen Überblick zu den Sprachfeatures von Java 15 verschafft haben, gehen wir jetzt weiter ins Detail. Records und spezielle Klassen sind das Thema dieses Artikels. Das Ziel: den Code einfacher und kompakter formulieren.

In diesem Artikel steigen wir direkt ein und sehen uns weitere Features des JDK Version 15 an. Konkret sind es Records, also eine leichtgewichtige Alternative zu Klassen, wenn es lediglich um die Speicherung von Daten geht. Dann wird es um Sealed Classes (versiegelte Klassen) und Hidden Classes (versteckte Klassen) gehen. Das alles sind fortgeschrittene Funktionen der objektorientierten Programmierung. Deren Ziel ist es, bestimmte Sachverhalte möglichst ausdruckstark, einfach und in kompakter Form im Java-Quellcode zu formulieren. Mit anderen Worten: Alles, was mit diesen neuen Features geht, war auch schon vorher möglich. Die Frage ist also: Lassen sich die Anforderungen mit der neuen Syntax besser, kürzer und prägnanter ausdrücken?

Datenklassen – Records

Bei der objektorientierten Programmierung werden die zu verwalteten Daten in Form von Objekten gehalten. Damit man ein solches Datenobjekt erstellen kann, sind zunächst die entsprechenden Klassen zu definieren. Typische Beispiele sind Klassen wie Person, Artikel, Mitarbeiter usw. Die Eigenschaften einer solchen Klasse leiten sich üblicherweise aus den Attributen der zugehörigen Tabellen einer relationalen Datenbank ab. Um eine Datenträgerklasse komplett zu erstellen, muss man viel redundanten und damit fehleranfälligen Code schreiben. Dazu gehören die lokalen Variablen für die interne Speicherung der Eigenschaften (Attribute), entsprechende Zugriffsmethoden in Form von Getter und Setter, mindestens ein Konstruktor und weitere Standardmethoden wie equals(), hashCode() und toString(). Im Alltag neigt man dann dazu, diese vermeintlichen Methoden wegzulassen, was zu späteren Problemen, unsauberem Code oder zu Schwierigkeiten beim Debuggen der Anwendung führen kann. Inhaltlich ist das alles kein Problem, jedoch ist das wiederholte Codieren solcher Datenklassen durchaus viel Arbeit, ein nerviger Prozess und damit bei manueller Durchführung auch schnell fehlerbehaftet. Integrierte Entwicklungsumgebungen bieten direkt bzw. über Plug-ins nachrüstbare Funktionen, um einige der genannten Boilerplates mehr oder weniger automatisch zu generieren. Auch wenn das von der Entwicklungsumgebung gut gelöst wird, wird am Ende pro Datenklasse eine Menge an Overhead in Form von eigentlich selbstverständlichem Quellcode produziert.

Das Ziel besteht darin, die Syntax für Datenklassen deutlich zu straffen. In den Dokumentationen zu den neuen Features des OpenJDK 15 [1] und Java JDK [2] wird das Problem auch an Beispielen beschrieben. Beispielhaft haben wir die Situation für eine Klasse Person in Listing 1 dargestellt. Es sind keine Überraschungen vorhanden, trotzdem lohnt sich ein Blick auf die einzelnen Bestandteile:

Listing 1

public class Person { private final String name; private final String beruf; public Person(String name, String beruf) { this.name = name; this.beruf = beruf; } public String getName() { return name; } public String getBeruf () { return beruf; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(name, person.name) && Objects.equals(beruf, person.beruf); } @Override public int hashCode() { return Objects.hash(name, beruf); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", beruf='" + beruf+ '\'' + '}'; } }
  • Felder: Wir definieren die Variablen für die Felder, in diesem Fall name (String) und beruf (String). Den Zugriff beschränken wir mittels private, sodass nur eine interne Verwendung in der Klasse stattfinden kann. Mittels final legen wir fest, dass das Attribut beim Aufruf des Programmes nur einmal gesetzt werden darf und danach nicht mehr veränderbar ist.

  • Konstruktor: Dieser hat zwei Parameter für die Werte von name und beruf. Innerhalb des Konstruktors werden die zuvor definierten Felder mit den übergebenen Werten initialisiert.

  • Getter: Es werden zwei Getter für das Lesen der beiden Attribute Name und Beruf definiert.

  • Setter: Haben wir hier nicht vorgesehen, da die Werte eines Objekts einer Datenklasse nicht veränderbar sein sollen.

  • Methode equals: Zwei Objekte der Klasse Person sind gleich, wenn alle Attribute übereinstimmen, in diesem Fall sind es die Werte für die Attribute Name und Beruf.

  • Methode hashCode: Standardimplementierung für die Generierung eines eindeutigen Hash-Codes für die Objekte dieser Klasse.

  • Methode toString: Der Rückgabewert (String) wird aus den Werten der Attribute zusammengesetzt.

Bitte beachten Sie, dass die Methoden equals(…), hashCode(…) und toString(…) mit @override gekennzeichnet sind und damit vorhandene Basismethoden überschrieben werden. Der Implementierungsaufwand für diese sehr einfache Klasse mit nur zwei Eigenschaften ist bereits beachtlich. Da Datenklassen ein Mapping der Tabellenspalten aus einer relationalen Datenbank sind, haben wir es i. d. R. mit einer Vielzahl von Eigenschaften zu tun, d. h., wir müssen in diesem Fall eine große Anzahl von Variablen, Getter usw. definieren. Insbesondere die Anpassung der o. g. Methoden verursacht einen großen Aufwand. Dieser Aufwand entsteht auch bei jeder Änderung des Quellcodes.

Aus diesen Gründen gibt es das neue Feature Records. Es wurden mit Java-Version 14 als Vorschaufunktion eingeführt. Das Ziel ist es, Datenklassen mit deutlich weniger Aufwand zu ermöglichen. Die Deklaration eines Datensatzes erfordert einen Namen, einen Header und einen Body. Der Header listet die Komponenten des Datensatzes auf, die die Eigenschaften des Datensatzes repräsentieren. In Bezug auf das Beispiel der Datenklasse aus Listing 1 verkürzt sich die Darstellung mit einem Record nun wie folgt:...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang