{"id":26216,"date":"2021-12-07T17:01:44","date_gmt":"2021-12-07T16:01:44","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=26216"},"modified":"2025-06-12T09:02:55","modified_gmt":"2025-06-12T07:02:55","slug":"java-records","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/java-records\/","title":{"rendered":"Java Records (mit Beispielen)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Records sind eine von zwei gro\u00dfen Neuerungen in <a href=\"\/de\/java\/java-16-features\/\">Java 16<\/a> (die zweite ist \u201ePattern Matching for instanceof\u201c). In diesem Artikel erf\u00e4hrst du:<\/p>\n\n\n\n<ul class=\"wp-block-list hc-checked-list\">\n<li>Was sind Java Records, und wof\u00fcr brauchen wir sie?<\/li>\n\n\n\n<li>Wie implementiert und benutzt man Records in Java?<\/li>\n\n\n\n<li>Wie kann man einen Java Record um zus\u00e4tzliche Funktionen erweitern? <\/li>\n\n\n\n<li>Was ist im Zusammenhang mit der Vererbung wichtig?<\/li>\n\n\n\n<li>Was ist bei der Serialisierung und Deserialisierung von Records zu beachten?<\/li>\n\n\n\n<li>Wozu braucht man Records, wenn man dessen Komponenten auch von der IDE ... oder von Lombok erzeugen lassen kann?<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Fangen wir mit einem Beispiel aus den Zeiten <em>vor<\/em> Records an...<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"wofuer-brauchen-wir-records\"><span style=\"font-size: revert; color: initial;\">Wof\u00fcr brauchen wir Records?<\/span> <\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Nehmen wir an, wir wollen eine unver\u00e4nderliche Klasse <code>Point<\/code> erstellen, mit <code>x<\/code>- und <code>y<\/code>-Koordinaten und allem, was man braucht, um diese Klasse sinnvoll einzusetzen. Wir wollen <code>Point<\/code>-Objekte erstellen, deren Felder auslesen und sie in Sets speichern oder als Keys in Maps verwenden k\u00f6nnen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Heraus k\u00e4me dabei in etwa der folgende Code:<\/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\">Point<\/span> <\/span>{\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">int<\/span> x;\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">int<\/span> y;\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>.x = x;\n    <span class=\"hljs-keyword\">this<\/span>.y = y;\n  }\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span> <span class=\"hljs-title\">getX<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> x;\n  }\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span> <span class=\"hljs-title\">getY<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> y;\n  }\n\n  <span class=\"hljs-meta\">@Override<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">boolean<\/span> <span class=\"hljs-title\">equals<\/span><span class=\"hljs-params\">(Object obj)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (obj == <span class=\"hljs-keyword\">this<\/span>) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n    <span class=\"hljs-keyword\">if<\/span> (obj == <span class=\"hljs-keyword\">null<\/span> || obj.getClass() != <span class=\"hljs-keyword\">this<\/span>.getClass()) <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">false<\/span>;\n    Point that = (Point) obj;\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">this<\/span>.x == that.x &amp;&amp; <span class=\"hljs-keyword\">this<\/span>.y == that.y;\n  }\n\n  <span class=\"hljs-meta\">@Override<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span> <span class=\"hljs-title\">hashCode<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> Objects.hash(x, y);\n  }\n\n  <span class=\"hljs-meta\">@Override<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">toString<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Point&#091;x=%d, y=%d]\"<\/span>.formatted(x, y);\n  }\n}<\/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 class=\"wp-block-paragraph\">Das ist schon eine ganze Menge Boilerplate-Code f\u00fcr die Anforderung \u201eeine Klasse mit x- und y-Werten\u201c.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wer <a href=\"https:\/\/projectlombok.org\/\" target=\"_blank\" rel=\"noopener\">Lombok<\/a> in seinen Projekten einsetzen wollte und durfte, war klar im Vorteil. Lombok kann Konstruktoren, Getter, <code>equals()<\/code>-, <code>hashCode()<\/code>- und <code>toString()<\/code>-Methoden automatisch erstellen. Der Code reduziert sich dadurch auf wenige Zeilen:<\/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-meta\">@AllArgsConstructor<\/span>\n<span class=\"hljs-meta\">@Getter<\/span>\n<span class=\"hljs-meta\">@EqualsAndHashCode<\/span>\n<span class=\"hljs-meta\">@ToString<\/span>\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Point<\/span> <\/span>{\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">int<\/span> x;\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">int<\/span> y;\n}<\/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 class=\"wp-block-paragraph\">Das ist schon deutlich komfortabler. Lombok ist ausgereift und integriert sich nahtlos in fast jede IDE. Ich setze es seit \u00fcber zehn Jahren immer wieder gerne ein.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Seit Java 16 geht es allerdings noch k\u00fcrzer:<\/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-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{}\n<\/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 class=\"wp-block-paragraph\">Mit Records wird aus den urspr\u00fcnglich 22 Zeilen \u2013 bzw. den 7 Zeilen mit Lombok \u2013 nur noch eine Zeile! Das ist nicht nur k\u00fcrzer, sondern auch sicherer (s. Abschnitte <a href=\"#java-records-vs-klassen\">Java Records vs. Klassen<\/a> und <a href=\"#java-records-vs-lombok\">Java Records vs. Lombok<\/a>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Schauen wir uns im Folgenden an, wie genau man Records schreibt und wie man sie nutzt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"wie-implementiert-und-benutzt-man-records-in-java\">Wie implementiert und benutzt man Records in Java?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Im vorherigen Abschnitt haben wir gesehen, wie man einen Record mit nur einer Zeile Code schreibt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><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 class=\"wp-block-paragraph\">Der Compiler generiert daraus die Klasse <code>Point<\/code> mit: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>den finalen Felder <code>int x<\/code> und <code>int y<\/code> (den sogenannten \u201eKomponenten\u201c des Records),<\/li>\n\n\n\n<li>einem Konstruktor, der beide Felder setzt (dem sogenannten \u201ekanonischen Konstruktor\u201c),<\/li>\n\n\n\n<li>den Accessor-Methoden <code>x()<\/code> und <code>y()<\/code> zum Lesen der Komponenten,<\/li>\n\n\n\n<li>einer <code>equals()<\/code>-Methode, die zwei <code>Point<\/code>-Instanzen als gleich einstuft, wenn deren <code>x<\/code>- und <code>y<\/code>-Koordinaten gleich sind,<\/li>\n\n\n\n<li>einer <code>hashCode()<\/code>-Methode, die f\u00fcr zwei gleiche <code>Point<\/code>-Instanzen den gleichen Hashwert liefert (im <code>Point<\/code>-Beispiel wird der Hashcode als x * 31 + y berechnet),<\/li>\n\n\n\n<li>einer <code>toString()<\/code>-Methode, die einen lesbaren Text liefert (im Beispiel \u201ePoint[x=..., y=...]\u201c).<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Du kannst <code>Point<\/code> wie eine regul\u00e4re Klasse einsetzen (in der ersten Zeile des folgenden Code-Beispiels wird der oben erw\u00e4hnte, automatisch generierte \u201ekanonische Konstruktor\u201c aufgerufen):<\/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\">Point p = <span class=\"hljs-keyword\">new<\/span> Point(<span class=\"hljs-number\">5<\/span>, <span class=\"hljs-number\">10<\/span>);\n<span class=\"hljs-keyword\">int<\/span> x = p.x();\n<span class=\"hljs-keyword\">int<\/span> y = p.y();<\/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 class=\"wp-block-paragraph\">Vergleichen kannst du zwei Punkte dann bspw. wie folgt:<\/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\">Point p1 = <span class=\"hljs-keyword\">new<\/span> Point(<span class=\"hljs-number\">8<\/span>, <span class=\"hljs-number\">4<\/span>);\nPoint p2 = <span class=\"hljs-keyword\">new<\/span> Point(<span class=\"hljs-number\">4<\/span>, <span class=\"hljs-number\">3<\/span>);\n<span class=\"hljs-keyword\">if<\/span> (p1.equals(p2)) {\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\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<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"java-record-konstruktoren\">Java Record Konstruktoren<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Im vorangegangenen Abschnitt hast du gelernt, dass der Compiler automatisch einen Konstruktor erzeugt, den sogenannten kanonischen Konstruktor. In diesem Kapitel erf\u00e4hrst du, wie du diesen kanonischen Konstruktor \u00fcberschreiben kannst, wie du sogenannte \u201ekompakte\u201c Konstruktoren schreiben kannst \u2013 und beliebige weitere nicht-kanonische Konstruktoren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"kanonischen-konstruktor-eines-records-ueberschreiben\">Kanonischen Konstruktor eines Records \u00fcberschreiben<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Wir k\u00f6nnen den kanonischen Konstruktor eines Records auch selbst implementieren:<\/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-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/** Canonical constructor as the compiler would generate it *\/<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>.x = x;\n    <span class=\"hljs-keyword\">this<\/span>.y = y;\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 class=\"wp-block-paragraph\">Sinn macht das aber erst, wenn wir vor oder nach der Zuweisung der Record-Felder zus\u00e4tzlichen Code ausf\u00fchren \u2013 z. B. k\u00f6nnten wir sicherstellen wollen, dass die Koordinaten nicht negativ sind:<\/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-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/** Canonical constructor *\/<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (x &lt; <span class=\"hljs-number\">0<\/span> || y &lt; <span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException();\n\n    <span class=\"hljs-keyword\">this<\/span>.x = x;\n    <span class=\"hljs-keyword\">this<\/span>.y = y;\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<p class=\"wp-block-paragraph\">Neben der Validierung k\u00f6nnten wir auch Parameter transformieren oder z. B. eine defensive Kopie eines Arrays erzeugen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wichtig ist bei dieser Form, dass die Konstruktor-Signatur exakt die gleiche ist wie die des Records. Folgendes ist hingegen nicht erlaubt:<\/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\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> a, <span class=\"hljs-keyword\">int<\/span> b)<\/span> <\/span>{  <span class=\"hljs-comment\">\/\/ Other names than x and y are not allowed!<\/span>\n    <span class=\"hljs-keyword\">this<\/span>.x = a;\n    <span class=\"hljs-keyword\">this<\/span>.y = b;\n  }\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 class=\"wp-block-paragraph\">Der Compiler w\u00fcrde das mit folgender Fehlermeldung quittieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ javac Point.java\nPoint.java:4: error: invalid canonical constructor in record Point\n    public Point(int a, int b) {\n           ^\n  (invalid parameter names in canonical constructor)\n1 error\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><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 class=\"wp-block-paragraph\">Ebenso wichtig ist, dass <em>alle<\/em> Felder gesetzt werden (logisch, sie sind ja final). W\u00fcrden wir nur <code>x<\/code> setzen, nicht aber <code>y<\/code>, dann w\u00fcrde der Compiler mit folgender Meldung abbrechen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ javac Point.java\nPoint.java:4: error: variable y might not have been initialized\n    }\n    ^\n1 error\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><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 class=\"wp-block-paragraph\">Interessanterweise muss keine 1:1-Zuordnung der Konstruktor-Parameter zu den Felder erfolgen. Es m\u00fcssen nicht einmal <em>alle<\/em> Parameter verwendet werden. So ist auch folgender Code g\u00fcltig:<\/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-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>.x = x;\n    <span class=\"hljs-keyword\">this<\/span>.y = x;  <span class=\"hljs-comment\">\/\/ Assigning this.y to x here - and ignoring y<\/span>\n  }\n}<\/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 class=\"wp-block-paragraph\">Gl\u00fccklicherweise erkennen moderne IDEs das. IntelliJ z. B. warnt hier mit \u201e'x' should probably not be assigned to 'y'\u201c.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Schlie\u00dflich darf die Sichtbarkeit des kanonischen Konstruktors nicht restriktiver sein als die Sichtbarkeit des Records selbst. Das bedeutet, dass ein als <em>private<\/em> gekennzeichneter Record einen als <em>public<\/em> markierten Konstruktor haben kann \u2013 ein als <em>public<\/em> deklarierter Record darf andersherum jedoch keinen privaten Konstruktor haben \u2013 folgendes ist also nicht erlaubt:<\/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\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{  <span class=\"hljs-comment\">\/\/ private constructor not allowed for public record<\/span>\n    <span class=\"hljs-keyword\">this<\/span>.x = x;\n    <span class=\"hljs-keyword\">this<\/span>.y = y;\n  }\n}<\/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 class=\"wp-block-paragraph\">Der Compiler w\u00fcrde das mit der folgenden Fehlermeldung quittieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">javac Point.java\nPoint.java:2: error: invalid canonical constructor in record Point\n  private Point(int x, int y) {\n          ^\n  (attempting to assign stronger access privileges; was public)\n1 error<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><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<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"kompakter-konstruktor-compact-constructor\">Kompakter Konstruktor (\u201eCompact Constructor\u201c)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Es gibt noch eine pr\u00e4gnantere Variante, um den kanonischen Konstruktor zu \u00fcberschreiben. Man kann die Parameter in der Signatur und die Zuweisungen komplett weglassen. Diese Art wird kompakter Konstruktor (\u201ecompact constructor\u201c) genannt:<\/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-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/** Compact constructor *\/<\/span>\n  <span class=\"hljs-keyword\">public<\/span> Point { <span class=\"hljs-comment\">\/\/ \u2190 No parameters here<\/span>\n    <span class=\"hljs-keyword\">if<\/span> (x &lt; <span class=\"hljs-number\">0<\/span> || y &lt; <span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException();\n    <span class=\"hljs-comment\">\/\/ \u2190 No assignments here<\/span>\n  }\n}<\/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 class=\"wp-block-paragraph\">Der Compiler f\u00fcgt die Zuweisungen <code>this.x = x<\/code> und <code>this.y = y<\/code> automatisch am Ende des Konstruktors ein und erzeugt damit letztendlich aus dem kompakten Konstruktor exakt denselben Bytecode wie aus dem im vorherigen Abschnitt als zweites gezeigten kanonischen Konstruktor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Paramter d\u00fcrfen innerhalb des Konstruktors auch ver\u00e4ndert werden, z. B. k\u00f6nnten wir stillschweigend alle negativen Werte durch 0 ersetzen:<\/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\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/** Compact constructor *\/<\/span>\n  <span class=\"hljs-keyword\">public<\/span> Point {\n    x = Math.max(x, <span class=\"hljs-number\">0<\/span>);\n    y = Math.max(y, <span class=\"hljs-number\">0<\/span>);\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 class=\"wp-block-paragraph\">Das w\u00fcrde dem folgenden kanonischen Konstruktor entsprechen:<\/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-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/** Canonical constructor *\/<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n    x = Math.max(x, <span class=\"hljs-number\">0<\/span>);\n    y = Math.max(y, <span class=\"hljs-number\">0<\/span>);\n    <span class=\"hljs-keyword\">this<\/span>.x = x;\n    <span class=\"hljs-keyword\">this<\/span>.y = y;\n  }\n}<\/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 class=\"wp-block-paragraph\">Beide Formen des Konstruktors sind letztendlich gleich, und es darf nur <em>entweder<\/em> ein kanonischer <em>oder<\/em> ein kompakter Konstruktor implementiert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Meine Empfehlung ist es, immer einen kompakten Konstruktor zu verwenden. Schlie\u00dflich wollen wir Programmiererinnen und Programmierer unsere Ideen zum Ausdruck bringen \u2013 und nicht unn\u00f6tigen Boilerplate-Code schreiben.<\/p>\n\n\n\n<div class=\"wp-block-uagb-info-box uagb-block-76088612 uagb-infobox__content-wrap  uagb-infobox-icon-left uagb-infobox-left uagb-infobox-stacked-mobile uagb-infobox-image-valign-top hc-infobox\"><div class=\"uagb-ifb-icon-wrap\"><svg xmlns=\"https:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\"><path d=\"M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z\"><\/path><\/svg><\/div><div class=\"uagb-ifb-content\"><div class=\"uagb-ifb-title-wrap\"><\/div><p class=\"uagb-ifb-desc\">Moderne IDEs wie IntelliJ k\u00f6nnen mit einem Klick einen kanonischen Konstruktor in einen kompakten Konstruktor umwandeln \u2013 und umgekehrt.<\/p><\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Achtung: Da die Komponenten des Records erst am Ende des Konstruktors gesetzt werden, sollte man nicht innerhalb des Konstruktors auf die Accessor-Methoden \u2013 im Beispiel <code>x()<\/code> und <code>y()<\/code> \u2013 zugreifen. Die Komponenten sind zu diesem Zeitpunkt noch mit Default-Werten belegt (im Fall von <code>int<\/code> also mit 0).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Man sollte stattdessen auf die (nicht explizit angegebenen) Konstruktor-Parameter zugreifen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/** Compact constructor *\/<\/span>\n  <span class=\"hljs-keyword\">public<\/span> Point {\n    System.out.println(x());  <span class=\"hljs-comment\">\/\/ Prints 0 (fields are not yet assigned)<\/span>\n    System.out.println(x);    <span class=\"hljs-comment\">\/\/ Prints the x parameter passed to the constructor<\/span>\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\">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 class=\"wp-block-paragraph\">Deutlich wird das, wenn man innerhalb des Konstruktors versucht \u00fcber <code>this<\/code> auf die Felder zuzugreifen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/** Compact constructor *\/<\/span>\n  <span class=\"hljs-keyword\">public<\/span> Point {\n    System.out.println(<span class=\"hljs-keyword\">this<\/span>.x);  <span class=\"hljs-comment\">\/\/ Not allowed - x is not yet initialized<\/span>\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><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 class=\"wp-block-paragraph\">Dieser Code f\u00fchrt zu einem Compilerfehler:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">javac Point.java\nPoint.java:3: error: variable x might not have been initialized\n    System.out.println(this.x);\n                           ^\n1 error\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><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 class=\"wp-block-paragraph\">Konsistent w\u00e4re es gewesen, auch den Zugriff \u00fcber <code>x()<\/code> und <code>y()<\/code> im Konstruktor zu verbieten.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"zusaetzliche-konstruktoren-in-records\">Zus\u00e4tzliche Konstruktoren in Records<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Records k\u00f6nnen um zus\u00e4tzliche Konstruktoren erweitert werden, wie z. B. einen Default-Konstruktor (einen ohne Parameter) oder einen, der <code>x<\/code> und <code>y<\/code> auf denselben Wert setzt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/** Default constructor *\/<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>(<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0<\/span>);\n  }\n\n  <span class=\"hljs-comment\">\/** Custom constructor *\/<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> value)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>(value, value);\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><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 class=\"wp-block-paragraph\">Dabei m\u00fcssen immer a) alle Felder gesetzt werden und b) muss das, wie im vorangegangenen Beispiel gezeigt, durch Delegation an den kanonischen Konstruktor per <code>this(...)<\/code> geschehen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Werte direkt zuzuweisen, wie in folgendem Code, ist hingegen erlaubt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/** Default constructor *\/<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>.x = <span class=\"hljs-number\">0<\/span>;  <span class=\"hljs-comment\">\/\/ Not allowed!<\/span>\n    <span class=\"hljs-keyword\">this<\/span>.y = <span class=\"hljs-number\">0<\/span>;  <span class=\"hljs-comment\">\/\/ Not allowed!<\/span>\n  }\n\n  <span class=\"hljs-comment\">\/** Custom constructor *\/<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> value)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>.x = value;  <span class=\"hljs-comment\">\/\/ Not allowed!<\/span>\n    <span class=\"hljs-keyword\">this<\/span>.y = value;  <span class=\"hljs-comment\">\/\/ Not allowed!<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><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 class=\"wp-block-paragraph\">Der Grund daf\u00fcr ist, dass immer \u2013 egal welchen Konstruktor man verwendet \u2013 die m\u00f6glicherweise im kanonischen oder kompakten Konstruktor implementierten Parameter-Validierungen aufgerufen werden sollen.<\/p>\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=\"statische-felder-in-records\">Statische Felder in Records<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Records k\u00f6nnen um statische Felder (finale sowie nicht-finale) erweitert werden. Beispielsweise k\u00f6nnten wir die 0 aus dem oben gezeigten Default-Konstruktor in eine Konstante extrahieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">int<\/span> ZERO = <span class=\"hljs-number\">0<\/span>;\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>(ZERO, ZERO);\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><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 class=\"wp-block-paragraph\">Wir k\u00f6nnten z. B. auch einen statischen Instanz-Counter hinzuf\u00fcgen, der im Konstruktor hochgez\u00e4hlt wird:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">long<\/span> instanceCounter = <span class=\"hljs-number\">0<\/span>;\n\n  <span class=\"hljs-keyword\">public<\/span> Point {\n    <span class=\"hljs-keyword\">synchronized<\/span> (Point<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>) <\/span>{\n      instanceCounter++;\n    }\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><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 class=\"wp-block-paragraph\">Tats\u00e4chlich w\u00fcrde ich so einen Counter eher als <code>AtomicLong<\/code> oder <code>LongAdder<\/code> implementieren \u2013 die w\u00e4ren dann allerdings wieder <code>final<\/code> und damit nicht als Beispiel f\u00fcr ein <em>nicht<\/em>-finales statischen Feld geeignet. ;-)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"methoden-in-records\">Methoden in Records<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Genau wie den kanonischen Konstruktor k\u00f6nnen wir auch die automatisch generierten Accessor-Methoden eines Records \u00fcberschreiben. Der folgende Record enth\u00e4lt eine Array-Komponente und erzeugt im Konstruktor und im Accessor jeweils eine defensive Kopie des Arrays, um \u00c4nderungen am im Record gespeicherten Array zu verhindern:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" 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> record <span class=\"hljs-title\">ImmutableArrayHolder<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span>&#091;] array)<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/* Compact constructor *\/<\/span>\n  <span class=\"hljs-keyword\">public<\/span> ImmutableArrayHolder {\n    array = array.clone();\n  }\n\n  <span class=\"hljs-comment\">\/* Accessor method *\/<\/span>\n  <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">int<\/span>&#091;] array() {\n    <span class=\"hljs-keyword\">return<\/span> array.clone();\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><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 class=\"wp-block-paragraph\">Neben zus\u00e4tzlichen Konstruktoren und statischen Feldern lassen sich in Java-Records auch zus\u00e4tzliche statische und nicht-statische Methoden definieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die folgende statische Methode gibt den Wert des Instanz-Z\u00e4hlers zur\u00fcck:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">long<\/span> instanceCounter = <span class=\"hljs-number\">0<\/span>;\n\n  <span class=\"hljs-comment\">\/\/ ... Constructor increasing instanceCounter ...<\/span>\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">synchronized<\/span> <span class=\"hljs-keyword\">long<\/span> <span class=\"hljs-title\">getInstanceCounter<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> instanceCounter;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><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<div class=\"wp-block-uagb-info-box uagb-block-4000d310 uagb-infobox__content-wrap  uagb-infobox-icon-left uagb-infobox-left uagb-infobox-stacked-mobile uagb-infobox-image-valign-top hc-infobox\"><div class=\"uagb-ifb-icon-wrap\"><svg xmlns=\"https:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\"><path d=\"M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z\"><\/path><\/svg><\/div><div class=\"uagb-ifb-content\"><div class=\"uagb-ifb-title-wrap\"><\/div><p class=\"uagb-ifb-desc\">Um <code>Point<\/code> threadsicher zu machen, wird jeglicher Zugriff auf <code>instanceCounter<\/code> synchronisiert. Das schlie\u00dft auch den Getter mit ein, um sicherzustellen, dass wir nicht einen im CPU-Core-Cache zwischengespeicherten Wert erhalten, sondern immer den aktuellen Wert aus dem Hauptspeicher.<\/p><\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Eine nicht-statische, also eine Instanz-Methode, k\u00f6nnten wir z. B. implementieren, um den euklidischen Abstand zu einem anderen Punkt zu berechnen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">distanceTo<\/span><span class=\"hljs-params\">(Point target)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">int<\/span> dx = target.x() - <span class=\"hljs-keyword\">this<\/span>.x();\n    <span class=\"hljs-keyword\">int<\/span> dy = target.y() - <span class=\"hljs-keyword\">this<\/span>.y();\n    <span class=\"hljs-keyword\">return<\/span> Math.sqrt(dx * dx + dy * dy);\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><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 class=\"wp-block-paragraph\">Aufrufen k\u00f6nnen wir die Methode z. B. wie in folgendem Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">Point p1 = <span class=\"hljs-keyword\">new<\/span> Point(<span class=\"hljs-number\">17<\/span>, <span class=\"hljs-number\">3<\/span>);\nPoint p2 = <span class=\"hljs-keyword\">new<\/span> Point(<span class=\"hljs-number\">18<\/span>, <span class=\"hljs-number\">12<\/span>);\n<span class=\"hljs-keyword\">double<\/span> distance = p1.distanceTo(p2);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><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 class=\"wp-block-paragraph\">Bei der Implementierung und dem Aufruf von Record-Methoden gibt es keinen Unterschied zu normalen Klassen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"records-und-vererbung\">Records und Vererbung<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Records k\u00f6nnen Interfaces implementieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" 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\">interface<\/span> <span class=\"hljs-title\">WithXCoordinate<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">int<\/span> <span class=\"hljs-title\">x<\/span><span class=\"hljs-params\">()<\/span><\/span>;\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> implements WithXCoordinate <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-30\"><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 class=\"wp-block-paragraph\">Das ist auch in Kombination mit den in <a href=\"\/de\/java\/java-17-features\/\">Java 17<\/a> ver\u00f6ffentlichten <a href=\"\/de\/java\/sealed-classes\/\">Sealed Types<\/a> m\u00f6glich:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" 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\">interface<\/span> <span class=\"hljs-title\">WithXCoordinate<\/span> <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">Point<\/span>, <span class=\"hljs-title\">Point3D<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">int<\/span> <span class=\"hljs-title\">x<\/span><span class=\"hljs-params\">()<\/span><\/span>;\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> implements WithXCoordinate <\/span>{}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y, <span class=\"hljs-keyword\">int<\/span> z)<\/span> implements WithXCoordinate <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><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 class=\"wp-block-paragraph\">Records k\u00f6nnen hingegen nicht von <em>Klassen<\/em> erben. Das folgende ist also nicht erlaubt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-32\" 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\">TaggedElement<\/span> <\/span>{\n  <span class=\"hljs-keyword\">private<\/span> String tag;\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> extends TaggedElement <\/span>{}  <span class=\"hljs-comment\">\/\/ Not allowed!<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><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 class=\"wp-block-paragraph\">Das liegt daran, dass Records bereits von der Klasse <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/21\/docs\/api\/java.base\/java\/lang\/Record.html\" target=\"_blank\" rel=\"noopener\">java.lang.Record<\/a> erben \u2013 und dass sie unver\u00e4nderlich sein sollen. Das w\u00e4ren sie nicht, wenn sie von einer ver\u00e4nderlichen Klasse erben w\u00fcrden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Records Sie sind au\u00dferdem implizit final, man kann also auch nicht <em>von<\/em> ihnen erben. Folgender Code ist also ebenfalls ung\u00fcltig:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-33\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TaggedPoint<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Point<\/span> <\/span>{  <span class=\"hljs-comment\">\/\/ Not allowed!<\/span>\n  <span class=\"hljs-keyword\">private<\/span> String tag;\n\n  TaggedPoint(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y, String tag) {\n    <span class=\"hljs-keyword\">super<\/span>(x, y);\n    <span class=\"hljs-keyword\">this<\/span>.tag = tag;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-33\"><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=\"besonderheiten-von-records\">Besonderheiten von Records<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Im Vergleich zu regul\u00e4ren Klassen sollte man bei Records einige Besonderheiten kennen. Diese erkl\u00e4re ich in den n\u00e4chsten Abschnitten.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"lokale-records\">Lokale Records<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Records d\u00fcrfen auch lokal (d. h. innerhalb von Methoden) definiert werden. Das kann insbesondere dann hilfreich sein, wenn man Zwischenergebnisse mit mehreren zusammengeh\u00f6rigen Variablen speichern m\u00f6chte.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Im folgenden Beispiel definieren wir innerhalb der <code>findFurthestPoint()<\/code>-Methode den lokalen Record <code>PointWithDistance<\/code>: eine Kombination aus einem <code>Point<\/code> und einem <code>double<\/code>-Wert, der die Entfernung des Punktes zu einem Ursprungspunkt repr\u00e4sentiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit Hilfe des lokalen Records f\u00fcllen wir eine Liste von Punkten und deren Entfernungen zum aktuellen Punkt. Aus dieser Liste ermitteln wir dann denjenigen <code>PointWithDistance<\/code> mit der gr\u00f6\u00dften Distanz \u2013 um daraus wiederum den zugeh\u00f6rigen <code>Point<\/code> zu extrahieren.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-34\" 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> Point <span class=\"hljs-title\">findFurthestPoint<\/span><span class=\"hljs-params\">(Point origin, Point... points)<\/span> <\/span>{\n  <span class=\"hljs-function\">record <span class=\"hljs-title\">PointWithDistance<\/span><span class=\"hljs-params\">(Point point, <span class=\"hljs-keyword\">double<\/span> distance)<\/span> <\/span>{}\n  \n  List&lt;PointWithDistance&gt; pointsWithDistance = <span class=\"hljs-keyword\">new<\/span> ArrayList&lt;&gt;();\n  <span class=\"hljs-keyword\">for<\/span> (Point point : points) {\n    <span class=\"hljs-keyword\">double<\/span> distance = origin.distanceTo(point);\n    pointsWithDistance.add(<span class=\"hljs-keyword\">new<\/span> PointWithDistance(point, distance));\n  }\n\n  PointWithDistance furthestPointWithDistance = Collections.max(\n      pointsWithDistance,\n      Comparator.comparing(PointWithDistance::distance));\n\n  <span class=\"hljs-keyword\">return<\/span> furthestPointWithDistance.point();\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><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=\"records-innerhalb-von-inneren-klassen\">Records innerhalb von inneren Klassen <\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Records d\u00fcrfen auch innerhalb von inneren Klassen definiert werden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-35\" 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\">OuterClass<\/span> <\/span>{\n  <span class=\"hljs-comment\">\/\/ ...<\/span>\n\n  <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">InnerClass<\/span> <\/span>{\n    <span class=\"hljs-function\">record <span class=\"hljs-title\">InnerClassRecord<\/span><span class=\"hljs-params\">(String foo, <span class=\"hljs-keyword\">int<\/span> bar)<\/span> <\/span>{}\n\n    <span class=\"hljs-comment\">\/\/ ...<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-35\"><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 class=\"wp-block-paragraph\">Diese M\u00f6glichkeit ist insofern erw\u00e4hnenswert, als dass sie erst mit dem finalen Release von Records durch <a href=\"https:\/\/openjdk.org:443\/jeps\/395\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 395<\/a> erm\u00f6glicht wurde.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"records-und-reflection\">Records und Reflection<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Finale Felder von regul\u00e4ren Klassen k\u00f6nnen problemlos per Reflection ver\u00e4ndert werden. Im folgenden Code ist <code>Point<\/code> die <em>Klasse<\/em> vom Beginn dieses Artikels.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-36\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">Point point = <span class=\"hljs-keyword\">new<\/span> Point(<span class=\"hljs-number\">10<\/span>, <span class=\"hljs-number\">5<\/span>);\nSystem.out.println(<span class=\"hljs-string\">\"point = \"<\/span> + point);\n\nField xField = Point<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>.<span class=\"hljs-title\">getDeclaredField<\/span>(\"<span class=\"hljs-title\">x<\/span>\")<\/span>;\nxField.setAccessible(<span class=\"hljs-keyword\">true<\/span>);\nSystem.out.println(<span class=\"hljs-string\">\"point.x = \"<\/span> + xField.get(point));\n\nxField.set(point, <span class=\"hljs-number\">55<\/span>);\nSystem.out.println(<span class=\"hljs-string\">\"point = \"<\/span> + point);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-36\"><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 class=\"wp-block-paragraph\">Der Code gibt folgendes aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-37\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">point = Point&#091;x=10, y=5]\npoint.x = 10\npoint = Point&#091;x=55, y=5]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-37\"><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 class=\"wp-block-paragraph\">Das bedeutet, wir haben per Reflection das eigentlich private und finale <code>x<\/code>-Feld der <code>Point<\/code>-Klasse ausgelesen und ge\u00e4ndert!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn wir den gleichen Code mit dem <code>Point<\/code>-<em>Record<\/em> aufrufen, dann erhalten wir folgende Ausgabe:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-38\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">point = Point&#091;x=10, y=5]\npoint.x = 10\nException in thread \"main\" java.lang.IllegalAccessException: \nCan not set final int field eu.happycoders.records.Point.x to java.lang.Integer<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-38\"><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 class=\"wp-block-paragraph\">Wir k\u00f6nnen also auch bei Records per Reflection private Felder auslesen (und damit z. B. einen Accessor umgehen, der eine defensive Kopie einer ver\u00e4nderlichen Komponente, wie z. B. einem Array, erzeugt).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Records sind aber im Gegensatz zu Klassen gesch\u00fctzt vor <em>Ver\u00e4nderungen<\/em> durch Reflection.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"records-deserialisieren\">Records deserialisieren<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Records haben eine Besonderheit beim Deserialisieren. Diese zeige ich an folgendem Beispiel.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Erweitern wir den <code>Point<\/code>-Konstruktor zun\u00e4chst um eine Parameter-Validierung. Sagen wir, wir wollen negative Werte ausschlie\u00dfen. Wir verwenden die kompakte Notation f\u00fcr die \u00dcberschreibung des kanonischen Konstruktors. Au\u00dferdem machen wir die Klasse serialisierbar:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-39\" 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> record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> implements Serializable <\/span>{\n  <span class=\"hljs-meta\">@Serial<\/span> <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">long<\/span> serialVersionUID = -<span class=\"hljs-number\">1482007299343243215L<\/span>;\n\n  <span class=\"hljs-keyword\">public<\/span> Point {\n    <span class=\"hljs-keyword\">if<\/span> (x &lt; <span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException(<span class=\"hljs-string\">\"x must be &gt;= 0\"<\/span>);\n    <span class=\"hljs-keyword\">if<\/span> (y &lt; <span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException(<span class=\"hljs-string\">\"y must be &gt;= 0\"<\/span>);\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-39\"><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 class=\"wp-block-paragraph\">Um den Unterschied beim Deserialisieren zu sehen, erstellen wir eine analoge regul\u00e4re Klasse <code>PointClass<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-40\" 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-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">PointClass<\/span> <span class=\"hljs-keyword\">implements<\/span> <span class=\"hljs-title\">Serializable<\/span> <\/span>{\n  <span class=\"hljs-meta\">@Serial<\/span> <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">long<\/span> serialVersionUID = <span class=\"hljs-number\">8411630734446201523L<\/span>;\n\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">int<\/span> x;\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">int<\/span> y;\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (x &lt; <span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException(<span class=\"hljs-string\">\"x must be &gt;= 0\"<\/span>);\n    <span class=\"hljs-keyword\">if<\/span> (y &lt; <span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException(<span class=\"hljs-string\">\"y must be &gt;= 0\"<\/span>);\n\n    <span class=\"hljs-keyword\">this<\/span>.x = x;\n    <span class=\"hljs-keyword\">this<\/span>.y = y;\n  }\n\n  <span class=\"hljs-comment\">\/\/ ... getters, equals(), hashCode(), toString() ...<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-40\"><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 class=\"wp-block-paragraph\">Wir kommentieren die Parameter-Validierung vor\u00fcbergehend aus und serialisieren mit folgendem Code einen ung\u00fcltigen <code>Point<\/code>-Record und eine ung\u00fcltige <code>PointClass<\/code>-Klasse in jeweils eine Datei:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-41\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">PointClass pc = <span class=\"hljs-keyword\">new<\/span> PointClass(-<span class=\"hljs-number\">5<\/span>, <span class=\"hljs-number\">5<\/span>);  <span class=\"hljs-comment\">\/\/ Parameter validation temporarily commented<\/span>\n<span class=\"hljs-keyword\">try<\/span> (FileOutputStream fileOut = <span class=\"hljs-keyword\">new<\/span> FileOutputStream(<span class=\"hljs-string\">\"point-class.bin\"<\/span>);\n    ObjectOutputStream objectOut = <span class=\"hljs-keyword\">new<\/span> ObjectOutputStream(fileOut)) {\n  objectOut.writeObject(pc);\n}\n\nPoint p = <span class=\"hljs-keyword\">new<\/span> Point(-<span class=\"hljs-number\">5<\/span>, <span class=\"hljs-number\">5<\/span>);  <span class=\"hljs-comment\">\/\/ Parameter validation temporarily commented<\/span>\n<span class=\"hljs-keyword\">try<\/span> (FileOutputStream fileOut = <span class=\"hljs-keyword\">new<\/span> FileOutputStream(<span class=\"hljs-string\">\"point-record.bin\"<\/span>);\n    ObjectOutputStream objectOut = <span class=\"hljs-keyword\">new<\/span> ObjectOutputStream(fileOut)) {\n  objectOut.writeObject(p);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-41\"><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 class=\"wp-block-paragraph\">Danach kommentieren wir die Parameter-Pr\u00fcfung wieder ein und versuchen die serialisierten Objekte zu deserialisieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-42\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">try<\/span> (FileInputStream fileIn = <span class=\"hljs-keyword\">new<\/span> FileInputStream(<span class=\"hljs-string\">\"point-class.bin\"<\/span>);\n    ObjectInputStream objectIn = <span class=\"hljs-keyword\">new<\/span> ObjectInputStream(fileIn)) {\n  PointClass pointClass = (PointClass) objectIn.readObject();\n  System.out.println(<span class=\"hljs-string\">\"pointClass = \"<\/span> + pointClass);\n}\n\n<span class=\"hljs-keyword\">try<\/span> (FileInputStream fileIn = <span class=\"hljs-keyword\">new<\/span> FileInputStream(<span class=\"hljs-string\">\"point-record.bin\"<\/span>);\n    ObjectInputStream objectIn = <span class=\"hljs-keyword\">new<\/span> ObjectInputStream(fileIn)) {\n  Point point = (Point) objectIn.readObject();\n  System.out.println(<span class=\"hljs-string\">\"point = \"<\/span> + point);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-42\"><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 class=\"wp-block-paragraph\">Das Egebnis macht einen weiteren Unterschied zwischen Records und Klassen sichtbar:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-43\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">pointClass = PointClass{x=-5, y=5}\nException in thread \"main\" java.io.InvalidObjectException: x must be &gt;= 0\n\tat ...\nCaused by: java.lang.IllegalArgumentException: x must be &gt;= 0\n\tat records.Point.&lt;init&gt;(Point.java:10)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-43\"><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 class=\"wp-block-paragraph\">Die fehlerhafte Klasse l\u00e4sst sich problemlos deserialisieren \u2013 der fehlerhafte Record hingegen nicht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der Grund: Bei der Deserialisierung einer Klasse werden die aus dem <code>ObjectInputStream<\/code> gelesenen Werte direkt in die Felder der Klasse geschrieben. Bei einem Record hingegen wird der kanonische Konstruktor aufgerufen \u2013 und damit die ggf. darin enthaltenen Parameter-\u00dcberpr\u00fcfungen ausgef\u00fchrt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"java-records-vs-klassen\">Java Records vs. Klassen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Ich bekomme oft die Frage gestellt, wozu man Records braucht, wenn man doch einfach Konstruktor, Getter, <code>equals()<\/code>, <code>hashCode()<\/code> und <code>toString()<\/code> von einer IDE generieren lassen kann.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Zum einen ist es meiner Meinung nach nicht die Aufgabe einer IDE, die Unzul\u00e4nglichkeiten einer Programmiersprache auszugleichen. Eine Programmiersprache sollte so ausgereift sein, dass wir mit m\u00f6glichst wenig Code unsere Ideen ausdr\u00fccken k\u00f6nnen \u2013 den Rest sollte der Compiler erledigen. Es verwenden auch nicht alle die gleiche IDE, und unterschiedliche IDEs generieren unterschiedlichen Quellcode.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Records haben weitere, konkrete Vorteile:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Die Felder von Records sind <em>wirklich<\/em> unver\u00e4nderlich. W\u00e4hrend bei einer regul\u00e4ren Klasse finale Felder per Reflection ver\u00e4ndert werden k\u00f6nnen, ist dies bei Records nicht m\u00f6glich (s. Abschnitt <a href=\"#records-und-reflection\">Records und Reflection<\/a>).<\/li>\n\n\n\n<li>Es ist nicht m\u00f6glich per Deserialisierung ung\u00fcltige Records zu erzeugen, da bei der Deserialisierung (im Gegensatz zu Klassen) der kanonische Konstruktor des Records aufgerufen wird.<\/li>\n\n\n\n<li>F\u00fcr die Methoden <code>equals()<\/code>, <code>hashCode()<\/code> und <code>toString()<\/code> erzeugt der Compiler einen speziellen Bytecode, der spezielle Implementierungen dieser Methoden in der JVM aufruft. So k\u00f6nnen diese Methoden in zuk\u00fcnftigen Java-Versionen immer weiter optimiert werden, ohne dass existierender Code neu kompiliert werden muss.<\/li>\n\n\n\n<li>Records arbeiten eng mit anderen Sprachmerkmalen zusammen, wie z. B. den in Java 21 finalisierten <a href=\"\/de\/java\/java-21-features\/#Record_Patterns_JEP_440\">Records Patterns<\/a>.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"java-records-vs-lombok\">Java Records vs. Lombok<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u00c4hnlich oft bekomme ich die Frage gestellt, was der Vorteil von Records gegen\u00fcber Lombok ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Meiner Meinung nach sollten wir nicht die Verantwortung f\u00fcr etwas, das eine Sprache k\u00f6nnen sollte, an eine Library abgeben. Denn das birgt Risiken: Was, wenn die Library nicht weiter gewartet wird? Was, wenn sie nicht an neue Java-Versionen angepasst oder gar komplett eingestellt wird?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Zudem gelten die gleichen konkreten Nachteilte wie bei regul\u00e4ren Klassen: Auch finale Felder von Klassen k\u00f6nnen per Reflection ver\u00e4ndert werden; durch Deserialisierung k\u00f6nnen ung\u00fcltige Instanzen erzeugt werden; <code>equals()<\/code>, <code>hashCode()<\/code> und <code>toString()<\/code> k\u00f6nnen nicht durch die JVM optimiert werden; und auch Pattern Matching funktioniert nicht mit Lombok-annotierten Klassen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"fazit\">Fazit<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Records bieten eine kompakte Notationsm\u00f6glichkeit, um Java-Klassen mit ausschlie\u00dflich finalen Feldern zu definieren. Records enthalten automatisch einen Konstruktor, der alle finalen Felder setzt (den kanonischen Konstruktor), lesende Zugriffsmethoden f\u00fcr alle Felder (die Accessor-Methoden), sowie durch die JVM optimierte <code>equals()<\/code>-, <code>hashCode()<\/code>- und <code>toString()<\/code>-Methoden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Records k\u00f6nnen um weitere Konstruktoren, statische Felder und statische sowie nicht-statische Methoden erweitert werden. Der kanonische Konstruktor kann \u00fcberschrieben werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Records k\u00f6nnen Interfaces implementieren (auch versiegelte), aber keine Klassen erweitern, und von ihnen kann auch nicht geerbt werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Beim Deserialisieren von Records wird immer deren kanonischer Konstruktor \u2013 und die darin ggf. enthaltenen Parameter-Validierungen \u2013 aufgerufen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Records wurden in <a href=\"\/de\/java\/java-14-features\/#Records_Preview\">Java 14<\/a> und <a href=\"\/de\/java\/java-15-features\/#Records_Second_Preview\">Java 15<\/a> als Preview-Features und durch <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/395\" target=\"_blank\">JDK Enhancement Proposal 395<\/a> in Java 16 als produktionsreif eingestuft. Records wurden im Rahmen von <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/projects\/amber\/\" target=\"_blank\">Projekt Amber<\/a> entwickelt, innerhalb dessen auch Switch Expressions, Text Blocks und Pattern Matching und <a href=\"\/de\/java\/sealed-classes\/\">Sealed Classes<\/a> entwickelt wurden.<\/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 neuen 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>Records sind eine von zwei gro\u00dfen Neuerungen in Java 16.<\/p>\n<p>Was sind Records, und wof\u00fcr brauchen wir sie? Wie implementiert und benutzt man Records? Wie kann man Records um zus\u00e4tzliche Funktionen erweitern? Was ist im Zusammenhang mit der Vererbung wichtig?<\/p>\n","protected":false},"author":1,"featured_media":34371,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_titles_title":"","_seopress_titles_desc":"Was sind Java Records? Wof\u00fcr brauchen wir sie? Wie implementiert + benutzt man Records? Kann man sie erweitern? K\u00f6nnen Records (ver)erben?","_seopress_robots_index":"","_seopress_robots_follow":"","_seopress_robots_imageindex":"","_seopress_robots_snippet":"","_seopress_robots_primary_cat":"none","_seopress_robots_breadcrumbs":"","_seopress_robots_freeze_modified_date":"","_seopress_robots_custom_modified_date":"","_seopress_robots_canonical":"","_seopress_social_fb_title":"","_seopress_social_fb_desc":"","_seopress_social_fb_img":"","_seopress_social_fb_img_attachment_id":0,"_seopress_social_fb_img_width":0,"_seopress_social_fb_img_height":0,"_seopress_social_twitter_title":"","_seopress_social_twitter_desc":"","_seopress_social_twitter_img":"","_seopress_social_twitter_img_attachment_id":0,"_seopress_social_twitter_img_width":0,"_seopress_social_twitter_img_height":0,"_seopress_redirections_value":"","_seopress_redirections_enabled":"","_seopress_redirections_enabled_regex":"","_seopress_redirections_logged_status":"both","_seopress_redirections_param":"","_seopress_redirections_type":301,"_seopress_analysis_target_kw":"java records,java record,record,records","_seopress_news_disabled":"","_seopress_video_disabled":"","_seopress_video":[],"_seopress_pro_schemas_manual":[{"_seopress_pro_rich_snippets_type":"none"}],"_seopress_pro_rich_snippets_disable_all":"","_seopress_pro_rich_snippets_disable":[],"_seopress_pro_schemas":[],"_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":25465,"_post_count":0,"footnotes":""},"categories":[64],"tags":[179],"class_list":["post-26216","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\/java-records-feature-image.jpg",1770,986,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image.jpg",150,84,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image.jpg",768,428,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image.jpg",1024,570,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-224x125.jpg",224,125,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-504x281.jpg",504,281,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-672x374.jpg",672,374,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-400x223.jpg",400,223,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-600x334.jpg",600,334,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-800x446.jpg",800,446,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-944x526.jpg",944,526,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-1200x668.jpg",1200,668,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image-1770x735.jpg",1770,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image.jpg",1536,856,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-records-feature-image.jpg",1770,986,false]},"uagb_author_info":{"display_name":"Sven Woltmann","author_link":"https:\/\/www.happycoders.eu\/de\/author\/sven\/"},"uagb_comment_info":2,"uagb_excerpt":"Records sind eine von zwei gro\u00dfen Neuerungen in Java 16. Was sind Records, und wof\u00fcr brauchen wir sie? Wie implementiert und benutzt man Records? Wie kann man Records um zus\u00e4tzliche Funktionen erweitern? Was ist im Zusammenhang mit der Vererbung wichtig?","public_identification_id":"327c92da34e04fe9973332b21b5d2291","private_identification_id":"477162dcb81c49a1ab368581c228e51a","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/26216","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=26216"}],"version-history":[{"count":10,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/26216\/revisions"}],"predecessor-version":[{"id":52468,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/26216\/revisions\/52468"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/34371"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=26216"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=26216"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=26216"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}