© Enkel/Shutterstock.com
JEP 360: Sealed Classes (Preview)

Kein Buch mit sieben Siegeln


Das Vorgehen hat sich bewährt – auch im JDK 15 hat mit Sealed Classes ein neues Sprachkonstrukt vorerst als Preview-Feature Einzug gehalten. Es gibt Entwicklern Kontrolle darüber, welche Klassen von einem bestimmten Interface oder einer Klasse erben dürfen. Wem das neue Sprachkonstrukt nützt, wann man es einsetzen kann und was man jetzt und in Zukunft alles damit anstellen können wird, wird in diesem Artikel zusammengefasst.

Java-Entwicklern stand bislang eine Vielzahl von Werkzeugen zur Verfügung, mit denen sie festlegen konnten, in welcher Art und Weise von Klassen vererbt werden kann. Ist eine Klasse package-private, kann sie nur im selben Paket referenziert werden, sämtliche Unterklassen müssen sich also in diesem befinden. Damit entfällt aber die Möglichkeit, die Oberklasse selbst außerhalb dieses Pakets zu nutzen. Mit dem final-Modifier kann das Erben von einer Klasse verboten werden, dies verhindert aber nicht, neue Implementierungen einer gemeinsamen Oberklasse zu entwerfen. Möchte man hingegen eine gemeinsame Oberklasse oder ein Interface etwa für APIs verwendbar machen, jedoch verhindern, dass neue Kindklassen implementiert und verwendet werden, existierte bislang lediglich die Möglichkeit, den Konstruktor der Oberklasse package-private zu setzen und sämtliche Unterklassen im selben Paket zu behalten. Genau hier setzen Sealed Classes an. Durch den neu eingeführten Modifier sealed und die Direktive permits wird bereits am oberen Ende der Vererbungshierarchie festgelegt, welche weiteren Implementierungen einer Klasse existieren dürfen. In Listing 1 definieren wir am Interface Payment, dass es nur durch die Klassen InvoicePayment und UpfrontPayment implementiert werden darf.

Listing 1

public sealed interface Payment permits InvoicePayment, UpfrontPayment { BigDecimal getAmount(); } public class InvoicePayment implements Payment { private final BigDecimal amount; private final LocalDate toPayUntil; public final InvoicePayment(BigDecimal amount, LocalDate toPayUntil) { this.amount = amount; this.toPayUntil = toPayUntil; } public BigDecimal getAmount() { return this.amount; } public LocalDate getToPayUntil() { return this.toPayUntil; } } public non-sealed class UpfrontPayment implements Payment { private final BigDecimal amount; public UpfrontPayment(BigDecimal amount) { this.amount = amount; } public BigDecimal getAmount() { return this.amount; } }

Auf gleiche Art und Weise könnte statt eines Interface auch eine Klasse oder eine abstrakte Klasse v...

Exklusives Abo-Special

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang