{"id":25994,"date":"2021-12-28T13:35:00","date_gmt":"2021-12-28T12:35:00","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=25994"},"modified":"2025-06-12T09:03:04","modified_gmt":"2025-06-12T07:03:04","slug":"sealed-classes","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/sealed-classes\/","title":{"rendered":"Sealed Classes in Java"},"content":{"rendered":"\n<p>Sealed Classes (deutsch: versiegelten Klassen) und Interfaces waren <em>die<\/em> gro\u00dfe Neuerung in <a href=\"\/de\/java\/java-17-features\/\">Java 17<\/a>. In diesem Artikel erf\u00e4hrst du:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Was sind versiegelte Klassen und Interfaces?<\/li>\n\n\n\n<li>Wie genau funktionieren versiegelte Klassen und Interfaces?<\/li>\n\n\n\n<li>Wof\u00fcr brauchen wir sie?<\/li>\n\n\n\n<li>Warum sollte man die Erweiterbarkeit einer Klassenhierarchie einschr\u00e4nken?<\/li>\n<\/ul>\n\n\n\n<p>Fangen wir an mit einem Beispiel...<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"ausgangslage-beispiel-klassenhierarchie\">Ausgangslage: Beispiel-Klassenhierarchie<\/h2>\n\n\n\n<p>Ausgangspunkt sei die folgende Klassenhierarchie:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"219\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-800x219.png\" alt=\"Sealed Classes Beispiel - Ausgangslage\" class=\"wp-image-25990\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-800x219.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-224x61.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-336x92.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-504x138.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-672x184.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-400x110.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-600x164.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-944x258.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point-1200x329.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-starting-point.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Sealed Classes Beispiel - Ausgangslage<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Hier der Java-Quellcode zu dem Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Circle<\/span>     <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Rectangle<\/span>  <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Square<\/span>     <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">WeirdShape<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TranspRectangle<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Rectangle<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">FilledRectangle<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Rectangle<\/span> <\/span>{ ... }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>F\u00fcr gew\u00f6hnlich kann jede Entwicklerin und jeder Entwickler diese Klassenhierarchie an allen Stellen erweitern. Eine erweiterte Struktur k\u00f6nnte wie folgt aussehen (die hinzugekommenen Klassen sind hellgelb gef\u00e4rbt):<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"305\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-800x305.png\" alt=\"Sealed Classes Beispiel - Erweiterungsm\u00f6glichkeiten ohne Versiegelung\" class=\"wp-image-25992\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-800x305.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-224x85.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-336x128.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-504x192.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-672x256.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-400x153.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-600x229.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-944x360.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem-1200x458.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-problem.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Sealed Classes Beispiel - Erweiterungsm\u00f6glichkeiten ohne Versiegelung<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Nun kann es sein, dass wir die Erweiterung unserer Klassenhierarchie einschr\u00e4nken wollen. Z. B. k\u00f6nnten wir festlegen wollen, dass Entwicklerinnen und Entwickler ausschlie\u00dflich die Klasse <code>WeirdShape<\/code> erweitern d\u00fcrfen.<\/p>\n\n\n\n<p>Warum k\u00f6nnten wir das wollen, und wie k\u00f6nnen wir das tun?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"warum-die-erweiterbarkeit-einer-klassenhierarchie-einschraenken\">Warum die Erweiterbarkeit einer Klassenhierarchie einschr\u00e4nken?<\/h2>\n\n\n\n<p>Es kann mehrere Gr\u00fcnde geben, warum wir die freie Erweiterbarkeit unserer Klassenhierarchie einschr\u00e4nken wollen:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Wir wollen den inneren Zustand einer Klasse bzw. einer Hierarchie von Klassen sch\u00fctzen und diesen nicht durch eine abgeleitete Klasse auf inkonsistente Weise manipulieren lassen.<\/li>\n\n\n\n<li>Wir wollen interne Objekte, deren Thread-Sicherheit durch unsere Klasse bzw. Klassenhierarchie garantiert wird, vor Ver\u00f6ffentlichung sch\u00fctzen, damit die Thread-Sicherheit nicht durch fremden Code gef\u00e4hrdet werden kann.<\/li>\n\n\n\n<li>Wir wollen sicherstellen, dass das Liskovsche Substitutionsprinzip (LSP) nicht verletzt wird. Das hei\u00dft: Wir wollen nicht, dass ein Entwickler eine abgeleitete Klasse implementiert, die den API-Vertrag der Elternklasse bricht.<\/li>\n\n\n\n<li>Wir wollen uns die <a href=\"#vollstaendigkeitsanalyse-bei-pattern-matching-for-switch\">Vollst\u00e4ndigkeitsanalyse bei \"Pattern Matching for switch\"<\/a> zunutze machen.<\/li>\n<\/ul>\n\n\n\n<p>Da wir jetzt die Gr\u00fcnde kennen, aus denen wir eine Klassenhierarchie einschr\u00e4nken wollen, kommen wir zur n\u00e4chsten Frage: Wie k\u00f6nnen wir das tun?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"klassenhierarchie-versiegeln-schritt-fuer-schitt\">Klassenhierarchie versiegeln \u2013 Schritt f\u00fcr Schitt<\/h2>\n\n\n\n<p>Die erste M\u00f6glichkeit kennen wir bereits...<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"klassenhierarchie-einschraenken-mit-final\">Klassenhierarchie einschr\u00e4nken mit \"final\"<\/h3>\n\n\n\n<p>Indem wir Klassen als \"final\" markieren, k\u00f6nnen wir deren Erweiterung generell verhindern.<\/p>\n\n\n\n<p>Eine zweite M\u00f6glichkeit w\u00e4re es eine Klasse als package-private zu markieren, um nur Unterklassen innerhalb desselben Pakets zu erlauben. Das h\u00e4tte allerdings zur Folge, dass die Oberklasse nicht mehr au\u00dferhalb des Pakets sichtbar w\u00e4re, was in den meisten F\u00e4llen unterw\u00fcnscht ist.<\/p>\n\n\n\n<p>Versuchen wir einmal \"final\" in unserem Beispiel einzusetzen. Wir markieren die Klassen <code>Circle<\/code>, <code>TranspRectangle<\/code>, <code>FilledRectangle<\/code> und <code>Square<\/code> als <code>final<\/code> (zur Erinnerung: <code>WeirdShape<\/code> soll als einzige Klasse erweiterbar bleiben).<\/p>\n\n\n\n<p>Die Erweiterungsm\u00f6glichkeiten unserer Klassenhierarchie werden dadurch wie in folgendem Klassendiagramm dargestellt eingeschr\u00e4nkt:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"305\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-800x305.png\" alt=\"Klassenhierarchie mit &quot;final&quot; einschr\u00e4nken\" class=\"wp-image-26022\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-800x305.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-224x85.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-336x128.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-504x192.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-672x256.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-400x153.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-600x229.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-944x360.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-1200x458.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Klassenhierarchie mit \"final\" einschr\u00e4nken<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Um die \u00dcbersicht zu verbessern, habe ich in der folgenden Grafik die durchgestrichenen K\u00e4stchen unter den finalen Klassen entfernt:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"305\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-800x305.png\" alt=\"Klassenhierarchie mit &quot;final&quot; einschr\u00e4nken\" class=\"wp-image-26023\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-800x305.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-224x85.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-336x128.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-504x192.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-672x256.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-400x153.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-600x229.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-944x360.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2-1200x458.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-final-2.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Klassenhierarchie mit \"final\" einschr\u00e4nken<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Damit sind wir auf einem guten Weg, aber noch lange nicht am Ziel. Was jetzt? <code>Shape<\/code> und <code>Rectangle<\/code> k\u00f6nnen wir offensichtlich nicht <code>final<\/code> machen, denn von diesen Klassen sollen ja andere erben.<\/p>\n\n\n\n<p>An dieser Stelle kommen die Sealed Classes zum Einsatz...<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"klassenhierarchie-versiegeln-mit-sealed-und-permits\">Klassenhierarchie versiegeln mit \"sealed\" und \"permits\"<\/h3>\n\n\n\n<p>Mit \"Sealed Classes\" k\u00f6nnen wir eine sogenannte \"versiegelte Klassenhierarchie\" implementieren. Das funktioniert wie folgt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Wir markieren die Klasse, deren Unterklassen wir restriktieren wollen, mit dem Keyword <code>sealed<\/code>.<\/li>\n\n\n\n<li>Mit dem Keyword <code>permits<\/code> listen wir die erlaubten Unterklassen auf.<\/li>\n<\/ul>\n\n\n\n<p>Wir erweitern den Code der Klassen <code>Shape<\/code> und <code>Rectangle<\/code> wie folgt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Shape<\/span> <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">Circle<\/span>, <span class=\"hljs-title\">Square<\/span>, <span class=\"hljs-title\">Rectangle<\/span>, <span class=\"hljs-title\">WeirdShape<\/span> <\/span>{ ... }\n\n<span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Rectangle<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">TranspRectangle<\/span>, <span class=\"hljs-title\">FilledRectangle<\/span> <\/span>{ ... }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Wir sagen mit diesem Code das Folgende aus: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Die Klasse <code>Shape<\/code> darf nur durch die Klassen <code>Circle<\/code>, <code>Square<\/code>, <code>Rectangle<\/code> und <code>WeirdShape<\/code> erweitert werden.<\/li>\n\n\n\n<li>Die Klasse <code>Rectangle<\/code> darf nur durch die Klassen <code>TranspRectangle<\/code> und <code>FilledRectangle<\/code> erweitert werden.<\/li>\n<\/ul>\n\n\n\n<p>Das folgende Klassendiagramm zeigt die durch <code>sealed<\/code> und <code>permits<\/code> hinzugekommenen Einschr\u00e4nkungen:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"305\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-800x305.png\" alt=\"Klassenhierarchie mit &quot;sealed&quot; und &quot;permits&quot; einschr\u00e4nken\" class=\"wp-image-26039\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-800x305.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-224x85.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-336x128.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-504x192.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-672x256.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-400x153.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-600x229.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-944x360.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-1200x458.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Klassenhierarchie mit \"sealed\" und \"permits\" einschr\u00e4nken<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Der \u00dcbersicht halber, hier noch einmal ohne die durchgestrichenen Klassen:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"305\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-800x305.png\" alt=\"Klassenhierarchie mit &quot;sealed&quot; und &quot;permits&quot; einschr\u00e4nken\" class=\"wp-image-26040\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-800x305.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-224x85.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-336x128.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-504x192.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-672x256.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-400x153.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-600x229.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-944x360.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2-1200x458.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-2.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Klassenhierarchie mit \"sealed\" und \"permits\" einschr\u00e4nken<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Es sieht so aus, als h\u00e4tten wir damit unser Ziel erreicht. Doch ein Schritt fehlt noch...<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"versiegelte-klassenhierarchie-mit-non-sealed-oeffnen\">Versiegelte Klassenhierarchie mit \"non-sealed\" \u00f6ffnen<\/h3>\n\n\n\n<p>Durch die bisherigen \u00c4nderungen sieht unser Code wie folgt aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Shape<\/span> <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">Circle<\/span>, <span class=\"hljs-title\">Square<\/span>, <span class=\"hljs-title\">Rectangle<\/span>, <span class=\"hljs-title\">WeirdShape<\/span> <\/span>{ ... }\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span>  <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Circle<\/span>     <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Rectangle<\/span>  <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">TranspRectangle<\/span>, <span class=\"hljs-title\">FilledRectangle<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span>  <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Square<\/span>     <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span>        <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">WeirdShape<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TranspRectangle<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Rectangle<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">FilledRectangle<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Rectangle<\/span> <\/span>{ ... }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Wenn wir versuchen diesen Code zu compilieren, erhalten wir die folgende Fehlermeldung:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ javac *.java\nWeirdShape.java:3: error: sealed, non-sealed or final modifiers expected\npublic class WeirdShape extends Shape {\n       ^<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Um versehentliche \u00d6ffnungen der versiegelten Klassenhierarchie zu verhindern, m\u00fcssen alle Klassen der Hierarchie mit <code>sealed<\/code>, <code>non-sealed<\/code> oder <code>final<\/code> markiert werden.<\/p>\n\n\n\n<p>Unsere Klasse <code>WeirdShape<\/code> soll erweiterbar sein, d. h. an dieser Klasse soll die Versiegelung ge\u00f6ffnet werden. Dazu m\u00fcssen wir diese Klasse mit <code>non-sealed<\/code> markieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> non-sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">WeirdShape<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Unsere abschlie\u00dfende Klassenhierarchie sieht damit so aus:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"305\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-800x305.png\" alt=\"Versiegelte Klassenhierarchie mit &quot;non-sealed&quot; \u00f6ffnen\" class=\"wp-image-26051\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-800x305.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-224x85.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-336x128.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-504x192.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-672x256.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-400x153.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-600x229.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-944x360.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed-1200x458.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed-classes-restrict-class-hierarchy-with-sealed-permits-non-sealed.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Versiegelte Klassenhierarchie mit \"non-sealed\" \u00f6ffnen<\/figcaption><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"pruefen-ob-eine-klasse-versiegelt-ist-und-welche-klassen-sie-erweitern-koennen\">Pr\u00fcfen, ob eine Klasse versiegelt ist und welche Klassen sie erweitern k\u00f6nnen<\/h3>\n\n\n\n<p>Die Klasse <code>Class<\/code> wurde um die folgenden zwei Methoden erweitert:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>isSealed()<\/code> \u2013 gibt <code>true<\/code> zur\u00fcck, wenn diese Klasse oder dieses Interface versiegelt ist.<\/li>\n\n\n\n<li><code>getPermittedSubclasses()<\/code> \u2013 gibt ein Array der Klassen oder Interfaces zur\u00fcck, die diese Klasse bzw. dieses Interface erweitern d\u00fcrfen, bzw. <code>null<\/code>, wenn diese Klasse\/dieses Interface nicht versiegelt ist.<\/li>\n<\/ul>\n\n\n<div class=\"convertkit-form wp-block-convertkit-form\" style=\"\"><script async data-uid=\"1427197203\" src=\"https:\/\/happycoders.kit.com\/1427197203\/index.js\" data-jetpack-boost=\"ignore\" data-no-defer=\"1\" data-no-optimize=\"1\" nowprocket><\/script><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"besonderheiten\">Besonderheiten<\/h2>\n\n\n\n<p>Bei der Verwendung von versiegelten Klassenhierarchien gilt es einige Besonderheiten zu beachten.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"versiegelung-innerhalb-einer-compilation-unit\">Versiegelung innerhalb einer \"Compilation Unit\"<\/h3>\n\n\n\n<p>Das Keyword <code>permits<\/code> kann weggelassen werden, wenn innerhalb einer Klassendatei (\"compilation unit\") von einer versiegelten Klasse abgeleitete Unterklassen definiert werden. Diese gelten dann als \"implizit deklarierte zul\u00e4ssige Unterklassen\" (\"implicitly declared permitted subclasses\"). <\/p>\n\n\n\n<p>In folgendem Beispiel ist <code>ChildInSameCompilationUnit<\/code> eine solche Unterklasse; das <code>permits<\/code>-Keyword darf daher weggelassen werden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SealedParentWithoutPermits<\/span> <\/span>{\n\n  <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ChildInSameCompilationUnit<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">SealedParentWithoutPermits<\/span> <\/span>{\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n  }\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"lokale-klassen\">Lokale Klassen<\/h3>\n\n\n\n<p>Lokale Klassen (also innerhalb von Methoden definierte Klassen) d\u00fcrfen versiegelte Klassen nicht erweitern.<\/p>\n\n\n\n<p>Der folgende Code zeigt eine lokale Klasse, die eine nicht versiegelte Klasse erweitert. Dieser Code ist g\u00fcltig: <\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">NonSealedParent<\/span> <\/span>{\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">doSomethingSmart<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">LocalChild<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">NonSealedParent<\/span> <\/span>{  <span class=\"hljs-comment\">\/\/ Allowed<\/span>\n      <span class=\"hljs-comment\">\/\/ ...<\/span>\n    }\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Wenn die \u00e4u\u00dfere Klasse allerdings versiegelt ist, darf die lokale Klasse nicht von ihr erben (auch nicht, wenn diese in der <code>permits<\/code>-Liste angegeben ist):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SealedParent<\/span> <\/span>{\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">doSomethingSmart<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">LocalChild<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">SealedParent<\/span> <\/span>{  <span class=\"hljs-comment\">\/\/ Not allowed<\/span>\n      <span class=\"hljs-comment\">\/\/ ...<\/span>\n    }\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"instanceof-tests-mit-versiegelten-klassen\"><code>instanceof<\/code>-Tests mit versiegelten Klassen<\/h3>\n\n\n\n<p>Bei <code>instanceof<\/code>-Tests pr\u00fcft der Compiler, ob die Klassenhierarchie es zul\u00e4sst, dass der Check jemals <code>true<\/code> ergeben kann. Ist das nicht der Fall, meldet der Compiler einen \"incompatible types\"-Fehler, wie z. B. in folgendem Code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">Number n = getNumber();\n<span class=\"hljs-keyword\">if<\/span> (n <span class=\"hljs-keyword\">instanceof<\/span> String) {  <span class=\"hljs-comment\">\/\/ Not allowed<\/span>\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ein <code>Number<\/code>-Objekt kann nie eine Instanz eines Strings sein. Der Compiler meldet daher:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><em>incompatible types: Number cannot be converted to String<\/em><\/p>\n\n\n\n<p>Auch die Informationen aus versiegelten Klassenhierarchien werden mit in diese Pr\u00fcfung aufgenommen. Was das bedeutet, erkl\u00e4re ich am besten an einem Beispiel:<\/p>\n\n\n\n<p>Nehmen wir an, wir haben ein Interface <code>A<\/code> und eine Klasse <code>B<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">A<\/span> <\/span>{}\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">B<\/span> <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Damit ist folgender Check valide:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">boolean<\/span> <span class=\"hljs-title\">isAaB<\/span><span class=\"hljs-params\">(A a)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> a <span class=\"hljs-keyword\">instanceof<\/span> B;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Wie kann dieser Check <code>true<\/code> ergeben? Indem wir eine Klasse <code>C<\/code> definieren, die von <code>B<\/code> erbt und <code>A<\/code> implementiert:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">C<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">B<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">A<\/span> <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Der Check <code>isAaB(new C())<\/code> ergibt dann <code>true<\/code>.<\/p>\n\n\n\n<p>Nun versiegeln wir das Interface <code>A<\/code> und erlauben als Unterklasse nur noch <code>AChild<\/code>; Klasse <code>B<\/code> lassen wir unver\u00e4ndet:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">A<\/span> <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">AChild<\/span> <\/span>{}\n<span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">AChild<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">A<\/span> <\/span>{}\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">B<\/span> <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Der Compiler erkennt nun, dass ein Objekt vom Typ <code>A<\/code> niemals auch eine Instanz von <code>B<\/code> sein kann. Entsprechend wird die Pr\u00fcfung <code>if (a instanceof B)<\/code> ab sofort mit folgendem Compilerfehler quittiert:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><em>incompatible types: A cannot be converted to B<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"contextual-keywords\">Contextual Keywords<\/h3>\n\n\n\n<p>Die Einf\u00fchrung neuer Keywords wie <code>sealed<\/code>, <code>non-sealed<\/code>, <code>permits<\/code> (oder auch <code>yield<\/code> aus den <a href=\"\/de\/java\/java-14-features\/#Switch_Expressions_Standard\">Switch-Expressions<\/a>) warf bei den JDK-Entwicklern folgende Frage auf: Was soll mit bestehendem Code passieren, der diese Keywords als Methoden- oder Variablennamen verwendet?<\/p>\n\n\n\n<p>Da Java einen hohen Wert auf Abw\u00e4rtskompatibilit\u00e4t legt, entschied man sich dazu bestehenden Code m\u00f6glichst nicht zu beeintr\u00e4chtigen. M\u00f6glich machen das sogenannte \"Contextual Keywords\" \u2013 Keywords, die nur in einem bestimmten Kontext eine Bedeutung haben.<\/p>\n\n\n\n<p>Die Begriffe <code>sealed<\/code> und <code>permits<\/code> z. B. sind solche \"Contextual Keywords\" und haben nur im Kontext der Klassendefinition eine Bedeutung. In anderen Kontexten k\u00f6nnen sie als Methoden- oder Klassenname verwendet werden. Folgendes ist also erlaubt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">sealed<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  <span class=\"hljs-keyword\">int<\/span> permits = <span class=\"hljs-number\">5<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vollstaendigkeitsanalyse-bei-pattern-matching-for-switch\">Vollst\u00e4ndigkeitsanalyse bei \"Pattern Matching for switch\" <\/h2>\n\n\n\n<p>In <a href=\"\/de\/java\/java-17-features\/#Pattern_Matching_for_switch_Preview\">Java 17<\/a> wurde \"Pattern Matching for switch\" als Preview-Feature vorgestellt. In Kombination mit diesem Feature erlauben versiegelte Klassen eine Ersch\u00f6pfungsanalyse, d. h. der Compiler kann pr\u00fcfen, ob ein <code>switch<\/code>-Statement oder -Ausdruck alle m\u00f6glichen F\u00e4lle abdeckt.<\/p>\n\n\n\n<p>Hier eine kleine Klassenhierarchie mit einem versiegelten Interface als Wurzel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">Color<\/span> <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">Red<\/span>, <span class=\"hljs-title\">Blue<\/span> <\/span>{}\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Red<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">Color<\/span> <\/span>{}\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Blue<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">Color<\/span> <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>\"Pattern Matching for switch\" erm\u00f6glicht Code wie den folgenden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">Color color = getColor();\n<span class=\"hljs-keyword\">switch<\/span> (color) {\n  <span class=\"hljs-keyword\">case<\/span> Red  r -&gt; ...\n  <span class=\"hljs-keyword\">case<\/span> Blue b -&gt; ...\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Der Compiler erkennt, dass das Objekt <code>color<\/code> nur eine Instanz von <code>Red<\/code> oder <code>Blue<\/code> sein kann; das <code>switch<\/code>-Statement ist also vollst\u00e4ndig und ben\u00f6tigt keinen <code>default<\/code>-Fall.<\/p>\n\n\n\n<p>Ein weiterer Vorteil ist, dass wir bei einer eventuellen sp\u00e4teren Erweiterung der Klassenhierachie vom Compiler auf den fehlenden <code>switch<\/code>-Fall hingewiesen werden.<\/p>\n\n\n\n<p>Erweitern wir unsere Klassenhierarchie um die Farbe gr\u00fcn (nicht vergessen: die <code>permits<\/code>-Liste von <code>Color<\/code> erweitern):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title\">Color<\/span> <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">Red<\/span>, <span class=\"hljs-title\">Blue<\/span>, <span class=\"hljs-title\">Green<\/span> <\/span>{}\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Red<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">Color<\/span> <\/span>{}\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Blue<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">Color<\/span> <\/span>{}\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Green<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">Color<\/span> <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Beim Versuch das <code>switch<\/code>-Statement zu compilieren bricht der Compiler jetzt mit folgender Fehlermeldung ab:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ javac --enable-preview -source 17 SwitchTest.java\nSwitchTest.java:6: error: the switch statement does not cover all possible input values\nswitch (color) {\n^\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Der Compiler kann uns also bei versiegelten Klassenhierarchien helfen unvollst\u00e4ndige <code>switch<\/code>-Statements oder -Ausdr\u00fccke \u2013 eine h\u00e4ufige Fehlerursache bei der Erweiterung von Klassenhierarchien \u2013 zu vermeiden.  <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"fazit\">Fazit<\/h2>\n\n\n\n<p>Versiegelte Klassen wurden durch <a href=\"https:\/\/openjdk.org:443\/jeps\/409\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 409<\/a> in Java 17 eingef\u00fchrt. Sie erlauben uns eine Klassenhierarchie vor ungew\u00fcnschten Erweiterungen zu sch\u00fctzen. <\/p>\n\n\n\n<p>F\u00fcr das in 17 als Preview-Feature eingef\u00fchrte <a href=\"\/de\/java\/java-17-features\/#Pattern_Matching_for_switch_Preview\">\"Pattern Matching for Switch\"<\/a> erm\u00f6glichen sie dar\u00fcber hinaus eine Vollst\u00e4ndigkeitsanalyse.<\/p>\n\n\n\n<p>Sealed Classes wurden zusammen mit anderen neuen Sprachfeatures wie Records, Switch Expressions, Text Blocks und Pattern Matching in <a href=\"https:\/\/openjdk.org:443\/projects\/amber\/\" target=\"_blank\" rel=\"noopener\">Projekt Amber<\/a> entwickelt.<\/p>\n<aside><p>Wenn dir der Artikel weitergeholfen hat, w\u00fcrde ich mich sehr \u00fcber eine positive Bewertung auf meinem <a href=\"https:\/\/www.provenexpert.com\/de-de\/sven-woltmann-happycoders-eu\/7smk\/\" target=\"_blank\" rel=\"noopener\">ProvenExpert-Profil<\/a> freuen. Dein Feedback hilft mir, meine Inhalte weiter zu verbessern und motiviert mich, neue informative Artikel zu schreiben.<\/p>\r\n                        <p>\ud83d\udc49 <a href=\"https:\/\/www.provenexpert.com\/de-de\/sven-woltmann-happycoders-eu\/7smk\/\" target=\"_blank\" rel=\"noopener\">Bewertung abgeben<\/a><\/p>\r\n                        <p>Du m\u00f6chtest \u00fcber alle neue Java-Features auf dem Laufenden sein? Dann <a href=\"#\" data-formkit-toggle=\"d8ee997126\">klicke hier<\/a>, um dich f\u00fcr den HappyCoders-Newsletter anzumelden.<\/p>\r\n                        <p>\ud83d\udc49 <a href=\"#\" data-formkit-toggle=\"d8ee997126\">Newsletter-Anmeldung<\/a><\/p><\/aside>","protected":false},"excerpt":{"rendered":"<p>Sealed Classes und Interfaces waren die gro\u00dfe Neuerung in Java 17.<\/p>\n<p>Was sind versiegelte Klassen und Interfaces? Wie genau funktionieren sie? Und warum brauchen wir sie?<\/p>\n","protected":false},"author":1,"featured_media":34349,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"none","_seopress_titles_title":"","_seopress_titles_desc":"Was sind Sealed Classes (\"versiegelte Klassen\") und Interfaces in Java? Wie genau funktionieren sie? Und warum brauchen wir sie?","_seopress_robots_index":"","_uag_custom_page_level_css":"","_wp_convertkit_post_meta":{"form":"-1","landing_page":"","tag":"0","restrict_content":"0"},"_metis_text_type":"standard","_metis_text_length":13121,"_post_count":0,"footnotes":""},"categories":[64],"tags":[179],"class_list":["post-25994","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java","tag-java-amber-de"],"uagb_featured_image_src":{"full":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java.jpg",1770,986,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java.jpg",150,84,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java.jpg",768,428,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java.jpg",1024,570,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-224x125.jpg",224,125,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-504x281.jpg",504,281,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-672x374.jpg",672,374,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-400x223.jpg",400,223,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-600x334.jpg",600,334,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-800x446.jpg",800,446,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-944x526.jpg",944,526,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-1200x668.jpg",1200,668,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java-1770x735.jpg",1770,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java.jpg",1536,856,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/sealed_classes_java.jpg",1770,986,false]},"uagb_author_info":{"display_name":"Sven Woltmann","author_link":"https:\/\/www.happycoders.eu\/de\/author\/sven\/"},"uagb_comment_info":0,"uagb_excerpt":"Sealed Classes und Interfaces waren die gro\u00dfe Neuerung in Java 17. Was sind versiegelte Klassen und Interfaces? Wie genau funktionieren sie? Und warum brauchen wir sie?","public_identification_id":"3177aa8b55574e6f82c4d321d97262aa","private_identification_id":"01b94fae68f34fc5bb44d80cdde697c1","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/25994","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/comments?post=25994"}],"version-history":[{"count":10,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/25994\/revisions"}],"predecessor-version":[{"id":52469,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/25994\/revisions\/52469"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/34349"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=25994"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=25994"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=25994"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}