Start / Seminare / Java SE Fortgeschrittene Sprachfeatures

Modul

Sealed Classes

2 Kapitel in diesem Modul-Video · Laufzeit

Vertonung mit synthetischer Stimme · Inhalte redaktionell verantwortet · © 2026 HECKER CONSULTING, alle Rechte vorbehalten

Transkript

Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.

Sealed Classes

0:00 Im ersten Modul haben wir geklärt, woraus ein Datentyp besteht. Jetzt kommt die andere Hälfte der Geschichte: Was kann etwas alles sein? Denken Sie an eine Buchung in einem Lager — sie ist ein Zugang oder ein Abgang oder eine Korrektur. Mehr Möglichkeiten gibt es nicht, und das ist eine fachliche Aussage, keine Momentaufnahme. Bis Java siebzehn ließ sich genau das nicht ausdrücken.

0:22 Man konnte eine Klasse dichtmachen oder offen lassen — dazwischen war nichts. Versiegelte Klassen und Schnittstellen schließen diese Lücke. In diesem Modul sehen wir, wie das geht, welche Pflichten daraus für die Untertypen entstehen und warum diese Pflichten der eigentliche Kern der Sache sind.

Sealed Classes

0:39 Wir bleiben beim ersten Tag und damit bei der Modellierung. Der Weg führt von der Entwurfsfrage — wann ist eine Hierarchie eigentlich fertig? — über die Schlüsselwörter sealed und permits bis zu den drei Zuständen, die jeder Untertyp annehmen muss. Am Ende schauen wir noch auf das Zusammenspiel mit Records, denn dort entfaltet die Versiegelung ihre eigentliche Wirkung.

1:00 Unser Lagerpuls-Beispiel bekommt in diesem Modul seine Buchungsarten. Die begleiten uns bis ins Modul zur Datenmodellierung, wo sich zeigt, was man mit einer vollständigen Variantenmenge alles anfangen kann. Vier Punkte stehen an. Der erste ist der wichtigste und der am wenigsten technische: Zu erkennen, wann eine Hierarchie abgeschlossen ist, ist eine Entwurfsleistung — die Sprache hilft Ihnen erst danach.

1:23 Der zweite Punkt ist Handwerk, sealed und permits sind schnell erklärt. Der dritte ist der, an dem die meisten Fehlermeldungen entstehen: Jeder Untertyp muss Stellung beziehen, und Java kennt genau drei erlaubte Antworten. Der vierte Punkt schlägt die Brücke zum nächsten Modul — Records und versiegelte Schnittstellen ergeben zusammen mehr als die Summe ihrer Teile.

Varianten mit versiegelten Typen modellieren

1:44 Beginnen wir mit dem Problem, nicht mit der Lösung. Sie modellieren einen Begriff aus der Fachlichkeit und wissen genau, welche Ausprägungen es gibt — drei Buchungsarten, vier Zahlungswege, zwei Belegtypen. Diese Information ist wertvoll, denn sie ist eine Aussage über den Entwurf. Und bis vor wenigen Jahren gab es in Java schlicht keinen Ort, an dem sie hätte stehen können.

2:07 Sie stand bestenfalls im Kommentar — und Kommentare prüft der Compiler bekanntlich nicht. Schauen wir uns an, was das gekostet hat. Eine versiegelte Klasse oder Schnittstelle nennt ausdrücklich, wer von ihr erben oder sie implementieren darf. Alles, was nicht auf dieser Liste steht, lehnt der Compiler ab. Ein Bild dazu: Denken Sie an eine Gästeliste. Nicht „bitte klingeln" und nicht „geschlossene Gesellschaft", sondern eine namentliche Liste — wer draufsteht, kommt rein.

2:35 Der eigentliche Gewinn ist dabei weniger die Sperre als die Aussage. Sie können jetzt in der Sprache selbst ausdrücken, dass eine Hierarchie fertig ist. Vorher stand das bestenfalls im Kommentar, und Kommentare prüft niemand beim Übersetzen. Warum ist das ein echter Zugewinn? Weil die alten Mittel nur die Extreme abdeckten. Final verbietet jede Ableitung, offen erlaubt jede — dazwischen gab es nichts.

3:00 Es gab einen bekannten Trick, den Konstruktor paketprivat zu machen, aber das war eine Nebenwirkung von Sichtbarkeitsregeln, kein Entwurf. Wer eine Bibliothek veröffentlicht, braucht die Möglichkeit zu sagen: Dieser Typ ist nicht zur Erweiterung gedacht. Und es gibt noch einen zweiten Grund, der uns im nächsten Modul beschäftigen wird: Nur wenn die Variantenmenge bekannt ist, kann der Compiler prüfen, ob Sie alle Fälle behandelt haben.

3:26 Diese Gegenüberstellung liest man am besten von oben nach unten als Entwicklungsgeschichte. Die ersten beiden Zeilen sind die Extreme, mit denen Java jahrzehntelang auskommen musste. Die dritte Zeile ist der Behelf — er funktioniert, aber er sagt nichts aus; wer ihn liest, sieht eine Sichtbarkeitsentscheidung, keine Entwurfsabsicht.

3:45 Erst die letzte Zeile trennt Absicht von Zufall. Und das ist der Punkt, auf den es mir hier ankommt: sealed ist weniger ein Schutzmechanismus als eine Form von Dokumentation, die der Compiler durchsetzt. Sie schreiben nicht auf, was verboten ist, sondern was vollständig ist. So sieht das in unserem Beispiel aus. Die Buchung ist der Oberbegriff, die drei genannten Typen sind alles, was es geben kann.

4:08 Achten Sie darauf, dass hier zwei verschiedene Entscheidungen nebeneinanderstehen, die gern verwechselt werden. Abstract sagt: Von diesem Typ soll es keine direkten Instanzen geben. Sealed sagt: Es soll keine fremden Untertypen geben. Das eine hat mit dem anderen nichts zu tun — Sie können eine versiegelte Klasse durchaus instanziierbar lassen.

4:28 In der Praxis treten beide meist zusammen auf, weil der Oberbegriff selten selbst ein sinnvoller Wert ist. Diese Aufgabe beginnt nicht in der IDE, sondern mit einer Frage an die Fachlichkeit: Steht die Variantenmenge wirklich fest? Genau das ist die Fähigkeit, die hier geübt wird — denn versiegeln sollten Sie nur, was auch fachlich abgeschlossen ist. Danach ist der Rest schnell erledigt.

4:51 Und dann kommt der lehrreichste Teil: Schreiben Sie den Ableitungsversuch von außen bewusst hin. Die Fehlermeldung, die Sie dabei bekommen, ist der Beweis, dass Ihre Aussage jetzt wirklich durchgesetzt wird — und nicht bloß freundlich empfohlen. Der häufigste Fehler beim Einstieg ist Übereifer: Nicht jede Hierarchie gehört versiegelt. Wenn Erweiterbarkeit das Ziel ist, wäre die Versiegelung ein Rückschritt.

5:15 Der zweite Punkt betrifft eine Verwechslung — sealed regelt Vererbung, nicht Sichtbarkeit; es ersetzt kein private. Der dritte ist eine Fehlersuche in die falsche Richtung: Wenn Sie eine Variante hinzufügen und die permits-Liste vergessen, meldet der Compiler das am Untertyp, obwohl der Fehler oben steht. Und der vierte ist eine Frage der Verantwortung: Wer versiegelt, verspricht Stabilität — nachträglich zu öffnen ist einfach, nachträglich zu schließen bricht fremden Code.

Sealed in der Praxis

5:42 Damit zur Mechanik. Sie besteht aus einer Handvoll Regeln, die schnell erzählt sind: ein Schlüsselwort, eine Liste, ein paar Randbedingungen. Eine dieser Regeln ist allerdings das eigentliche Herzstück, und sie betrifft nicht die Basisklasse, sondern die Untertypen. Ohne sie wäre die ganze Versiegelung genau eine Ebene tief — und damit in der Praxis wertlos, weil jeder sie mit einer einzigen Zwischenklasse aushebeln könnte.

6:06 Achten Sie im Folgenden besonders auf diesen Punkt, alles andere ergibt sich fast von selbst. Der Ablauf hat fünf Schritte, aber eigentlich nur zwei Gedanken. Der erste: Oben sagen, wer dazugehört — das sind sealed und die permits-Liste. Der zweite: Unten sagen, wie es weitergeht — und das ist Schritt drei, der Pflichtteil.

6:26 Jeder genannte Untertyp muss selbst einen der drei Zustände tragen, sonst übersetzt er schlicht nicht. Dazu kommen zwei praktische Randbedingungen: Alle Beteiligten müssen im selben Paket oder Modul liegen, damit der Compiler die Menge überhaupt kennen kann. Und wenn ohnehin alles in einer Quelldatei steht, dürfen Sie sich die permits-Liste sparen.

6:47 Hier stehen alle drei Möglichkeiten direkt untereinander, und das lohnt den genauen Blick. Der Zugang ist final — bei ihm ist Schluss. Der Abgang ist selbst wieder versiegelt und führt die Beschränkung eine Ebene tiefer fort, mit zwei eigenen Varianten. Und die Korrektur ist non-sealed, öffnet ihren Zweig also ausdrücklich wieder.

7:06 Wichtig ist mir dabei die Lesart: Das sind keine drei technischen Varianten desselben, sondern drei verschiedene Aussagen über Ihren Entwurf. Wer diesen Code liest, weiß hinterher, wo die Hierarchie zu Ende ist und wo sie weiterwachsen darf. Warum diese Pflicht überhaupt? Stellen Sie sich vor, es gäbe sie nicht. Sie versiegeln oben sorgfältig die Basisklasse — und der erste Untertyp lässt sich frei ableiten.

7:30 Damit wäre die ganze Beschränkung genau eine Ebene tief und in der Praxis wertlos, weil jeder sie mit einer Zwischenklasse umgehen könnte. Deshalb verlangt Java von jedem Untertyp eine Stellungnahme. Final beendet die Kette, sealed setzt die Beschränkung fort, non-sealed öffnet bewusst. Genau diese Kette ist es, die aus einer lokalen Regel eine Aussage über die gesamte Hierarchie macht.

7:53 Bleibt die Frage, wozu man freiwillig wieder öffnet. Der Anwendungsfall ist konkreter, als man denkt: Sie wollen den Kern Ihres Modells geschlossen halten, aber einen bestimmten Zweig für fremde Erweiterungen freigeben. In Lagerpuls könnten das eigene Korrekturarten sein, die ein angeschlossenes System beisteuert. Der entscheidende Unterschied zu einer offenen Hierarchie ist, dass diese Öffnung im Code steht und gelesen wird.

8:17 Sie bezahlen dafür einen Preis, den Sie kennen sollten: Für diesen Zweig geben Sie die Vollständigkeit auf — der Compiler kann dort später keine lückenlose Fallunterscheidung mehr garantieren. Diese vier Regeln haben alle denselben Ursprung: Der Compiler muss die Variantenmenge zum Übersetzungszeitpunkt vollständig kennen.

8:36 Deshalb die Pflicht zur Stellungnahme, deshalb die Beschränkung auf ein Paket oder Modul, deshalb die Erleichterung bei einer einzelnen Quelldatei — dort sieht er ohnehin alles. Die letzte Zeile ist die interessanteste und zugleich die Überleitung: Records sind implizit final. Sie können deshalb nie sealed sein, was auch keinen Sinn ergäbe.

8:55 Aber sie dürfen Schnittstellen implementieren, und damit sind wir bei der Kombination, um die es gleich geht. Und hier ist sie, diese Kombination. Die versiegelte Schnittstelle sagt: Es gibt genau zwei Arten von Belegen. Die Records sagen: Und so sieht jeder von ihnen aus. Zusammen ergibt das ein vollständiges Modell aus wenigen Zeilen — ohne gemeinsame Basisklasse, ohne Felder, die nur in der Hälfte der Fälle gefüllt sind.

9:21 Jeder Beleg trägt genau seine eigenen Daten. Diese Kombination ist so wirkungsvoll, dass wir ihr im nächsten Modul ein eigenes Kapitel widmen. Dort kommt dann noch die dritte Zutat dazu: eine Fallunterscheidung, deren Vollständigkeit der Compiler prüft. In dieser Aufgabe treffen Sie für jeden Untertyp eine Entscheidung — und der eigentliche Auftrag ist die Begründung. Notieren Sie zu jedem Zustand einen Satz, warum er dort steht.

9:47 Das klingt nach Fleißarbeit, ist aber der Kern der Übung: Diese Sätze sind später Ihre Entwurfsdokumentation, und sie sind genau die Information, die einem Kollegen in sechs Monaten fehlt. Erkennen können Sie den Erfolg an zwei Dingen: Das Modul übersetzt, und der bewusst geöffnete Zweig lässt sich tatsächlich von außen ableiten — alle anderen nicht.

10:07 Der erste Punkt kostet in der Praxis die meiste Zeit: Liegen die Untertypen im falschen Paket, meldet der Compiler zwar etwas, aber der Zusammenhang mit sealed ist nicht sofort offensichtlich. Der zweite ist eine Bequemlichkeitsfalle — non-sealed macht jede Fehlermeldung weg, aber es öffnet eben auch die Hierarchie; wenn der Compiler final verlangt, hat er meist recht.

10:28 Der dritte begegnet Ihnen, sobald Sie Records ins Spiel bringen: Sie sind implizit final, Ableiten ist ausgeschlossen. Und der vierte ist reine Wartung — permits-Liste und tatsächliche Untertypen müssen zusammenpassen. Halten wir fest: sealed drückt aus, dass eine Variantenmenge vollständig ist — das ist eine Aussage über Ihren Entwurf, die der Compiler durchsetzt.

10:49 Die permits-Liste nennt die erlaubten Untertypen und darf bei einer einzelnen Quelldatei entfallen. Jeder Untertyp bezieht Stellung, und diese Pflicht ist kein Formalismus, sondern das, was die Versiegelung über die ganze Hierarchie trägt. Records passen dazu ausgezeichnet, weil sie ohnehin final sind. Im nächsten Modul setzen wir beide Bausteine zusammen — und sehen, was ein Datenmodell leisten kann, wenn UND und ODER sauber getrennt sind.

Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →