{"id":53935,"date":"2025-12-03T21:29:04","date_gmt":"2025-12-03T20:29:04","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=53935"},"modified":"2025-12-04T09:42:56","modified_gmt":"2025-12-04T08:42:56","slug":"java-26-features","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/java-26-features\/","title":{"rendered":"Java 26 Features (mit Beispielen)"},"content":{"rendered":"\n<p>Java 26 befindet sich seit dem 4. Dezember 2025 in der sogenannten \u201eRampdown Phase One\u201d, d. h. es werden keine weiteren JDK Enhancement Proposals (JEPs) in das Release aufgenommen. Das Feature-Set steht also fest. Es werden nur noch Bugs gefixt und ggf. kleinere Verbesserungen durchgef\u00fchrt.<\/p>\n\n\n\n<p>Als Ver\u00f6ffentlichungsdatum ist der 17. M\u00e4rz 2026 angepeilt. Die aktuelle Early-Access-Version kannst du <a href=\"https:\/\/jdk.java.net\/26\/\" target=\"_blank\" rel=\"noopener\">hier<\/a> herunterladen.<\/p>\n\n\n\n<p>Java 26 geh\u00f6rt mit 10 gelieferten JDK Enhancement Proposals (JEPs) zu den \u00fcberschaubareren Releases der letzten Jahre. Die H\u00e4lfte der JEPs sind kleinere bis mittelgro\u00dfe \u00c4nderungen \u2013 wie <a href=\"#Prepare_to_Make_Final_Mean_Final_-_JEP_500\">Warnungen bei der Mutation von finalen Feldern<\/a> und die <a href=\"#HTTP3_for_the_HTTP_Client_API_-_JEP_517\">Unterst\u00fctzung von HTTP\/3<\/a>.<\/p>\n\n\n\n<p>Die andere H\u00e4lfte sind wiedervorgelegte Previews \u2013 also Aktualisierungen von bereits vorgestellten, aber noch nicht finalisierten Features. Bis auf bei <a href=\"#Lazy_Constants_Second_Preview_-_JEP_526\">Lazy Constants<\/a> (zuvor bekannt als <em>Stable Values<\/em>) gab es hier nur minimale \u00c4nderungen.<\/p>\n\n\n\n<p>F\u00fcr alle JEPs und \u00c4nderungen aus den Release Notes verwende ich wie immer die originalen, englischen Bezeichnungen.<\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"prepare-to-make-final-mean-final-jep-500\">Prepare to Make Final Mean Final \u2013 JEP 500<\/h2>\n\n\n\n<p>Die meisten Entwickler:innen gehen davon aus, dass ein Feld, das wir als <code>final<\/code> kennzeichnen, nicht ver\u00e4nderbar ist. Tats\u00e4chlich k\u00f6nnen wir einem <code>final<\/code>-Feld auch nicht einfach per Gleich-Zeichen einen neuen Wert zuweisen. Allerdings erlaubt es uns die sogenannte <a href=\"https:\/\/www.happycoders.eu\/de\/java\/deep-reflection-integer-string-modifizieren\/\">Deep Reflection<\/a>, diese Einschr\u00e4nkung zu umgehen.<\/p>\n\n\n\n<p>Hier eine kleine Beispielklasse, der wir im Konstruktor einen Wert \u00fcbergeben, der dann in dem finalen Feld <code>value<\/code> gespeichert wird:<\/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\">Box<\/span> <\/span>{\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> Object value;\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Box<\/span><span class=\"hljs-params\">(Object value)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>.value = value;\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\">\"Box{value=\"<\/span> + value + <span class=\"hljs-string\">\"}\"<\/span>;\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>Der folgende Code zeigt, wie sich der Inhalt des finalen Feldes kinderleicht \u2013 sogar von au\u00dferhalb des Objekts \u2013 \u00e4ndern l\u00e4sst:<\/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\">Box box = <span class=\"hljs-keyword\">new<\/span> Box(<span class=\"hljs-string\">\"Rubic's Cube\"<\/span>);\n\nIO.println(<span class=\"hljs-string\">\"box = \"<\/span> + box);\n\nField valueField = Box<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>.<span class=\"hljs-title\">getDeclaredField<\/span>(\"<span class=\"hljs-title\">value<\/span>\")<\/span>;\nvalueField.setAccessible(<span class=\"hljs-keyword\">true<\/span>);\nvalueField.set(box, <span class=\"hljs-string\">\"Magic Wand\"<\/span>);\n\nIO.println(<span class=\"hljs-string\">\"box = \"<\/span> + box);<\/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 umgehen hier sowohl die Kapselung des Feldes per <code>private<\/code> als auch die Unver\u00e4nderlichkeit via <code>final<\/code>. Und dieser Code l\u00e4sst sich von beliebiger Stelle aus ausf\u00fchren, beispielsweise auch von Drittanbieter-Libraries, von denen wir nicht mal wissen, dass sie auf dem Classpath liegen. <\/p>\n\n\n\n<p>Dieses Problem wurde bereits vor Jahren erkannt, und daher wurde bei Hidden Classes in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-15-features\/#hidden-classes\">Java 15<\/a> und bei <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-records\/\">Records<\/a> in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-16-features\/#records\">Java 16<\/a> von Beginn an Deep Reflection gar nicht erst erlaubt.<\/p>\n\n\n\n<p>Zudem kam ebenfalls in Java 16 die \u201eStrong Encapsulation\u201c f\u00fcr JDK-Interna. Seitdem m\u00fcssen wir Deep Reflection \u00fcber Modulgrenzen hinweg explizit mit <code>--add-opens<\/code> erlauben. Das funktioniert bei eigenen Anwendungen aber nur, wenn diese auch das Modulsystem nutzen.<\/p>\n\n\n\n<p>Um Java sicherer zu machen, soll die Modifkation finaler Felder per Deep Reflection in Zukunft grunds\u00e4tzlich verboten werden \u2013 auch innerhalb eines Moduls.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Warnungen ab Java 26<\/h4>\n\n\n\n<p>In Java 26 werden durch <a href=\"https:\/\/openjdk.org\/jeps\/500\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 500<\/a> als ein erster Schritt Warnungen eingef\u00fchrt. Der oben gezeigte Code l\u00e4sst sich unter Java 25 anstandslos ausf\u00fchren; unter Java 26 zeigt er nun folgende Warnung an:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">WARNING: Final field value in class eu.happycoders.java26.jep500.Box has been mutated reflectively by class eu.happycoders.java26.jep500.FinalTest in unnamed module @3f99bd52\nWARNING: Use --enable-final-field-mutation=ALL-UNNAMED to avoid a warning\nWARNING: Mutating final fields will be blocked in a future release unless final field mutation is enabled<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><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>Die Nutzung von Deep Reflection kann per <code>--enable-final-field-mutation=&lt;Modulname&gt;<\/code> explizit f\u00fcr bestimmte Module erlaubt \u2013 und damit die Warnung verhindert werden.<\/p>\n\n\n\n<p>In einer zuk\u00fcnftigen Java-Version soll Deep Reflection dann standardm\u00e4\u00dfig verboten sein \u2013 statt einer Warnung wird es dann zu einer Exception kommen, sofern Deep Reflection nicht per <code>--enable-final-field-mutation<\/code> explizit erlaubt ist.<\/p>\n\n\n\n<p>Das zuk\u00fcnftige Verhalten kann bereits jetzt durch die VM-Option <code>--illegal-final-field-mutation<\/code> eingeschaltet werden. Die Option bietet folgende M\u00f6glichkeiten:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><code style=\"white-space:nowrap\">--illegal-final-field-mutation=allow<\/code><\/td><td>Finale Felder k\u00f6nnen ohne Warnung ver\u00e4ndert werden (Standardverhalten vor Java 26).<\/td><\/tr><tr><td><code style=\"white-space:nowrap\">--illegal-final-field-mutation=warn<\/code><\/td><td>Beim <em>erstmaligen<\/em> \u00c4ndern eines finalen Feldes erscheint eine Warnung (Standardverhalten ab Java 26).<\/td><\/tr><tr><td><code style=\"white-space:nowrap\">--illegal-final-field-mutation=debug<\/code><\/td><td>Bei <em>jedem<\/em> \u00c4ndern eines finalen Feldes erscheint eine Warnung.<\/td><\/tr><tr><td><code style=\"white-space:nowrap\">--illegal-final-field-mutation=deny<\/code><\/td><td>Finale Felder d\u00fcrfen nicht ge\u00e4ndert werden \u2013 der Versuch f\u00fchrt zu einer <code>IllegalAccessException<\/code>.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>In einer zuk\u00fcnftigen Java-Version wird <code>deny<\/code> zur Standardeinstellung werden, und <code>allow<\/code> wird nicht mehr erlaubt sein. Dann muss Deep Reflection auf Modulebene per <code>--enable-final-field-mutation<\/code> aktiviert werden. <\/p>\n\n\n\n<p>Die Garantie, dass finale Felder wirklich final sind, sch\u00fctzt \u00fcbrigens nicht nur vor unerwartetem Verhalten, sondern sie verbessert auch die Performance einer Anwendung: Wenn die JVM wei\u00df, dass ein Feld nicht ver\u00e4ndert werden kann, dann kann es den Zugriff darauf per <a href=\"https:\/\/en.wikipedia.org\/wiki\/Constant_folding\" target=\"_blank\" rel=\"noopener\">Constant Folding<\/a> \u2013 eine Art Inlining f\u00fcr Konstanten \u2013 optimieren.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"ahead-of-time-object-caching-with-any-gc-jep-516\">Ahead-of-Time Object Caching with Any GC \u2013 JEP 516<\/h2>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#ahead-of-time-class-loading-linking-jep-483\">Java 24<\/a> wurde <a href=\"https:\/\/www.happycoders.eu\/de\/java\/ahead-of-time-class-loading-and-linking\/\">Ahead-of-Time Class Loading &amp; Linking<\/a> eingef\u00fchrt \u2013 die M\u00f6glichkeit, die von einer Anwendung ben\u00f6tigten Klassen in einem architekturspezifischen Bin\u00e4rformat in einem sogenannten Ahead-of-Time-Cache zu speichern \u2013 und aus diesem zu laden, um den Start von Anwendungen deutlich zu beschleunigen (in Tests um bis zu 42 %).<\/p>\n\n\n\n<p>Bisher wurden die Klassen exakt so im Cache gespeichert, wie sie der Garbage Collector auf dem Heap ablegt, einschlie\u00dflich Header ud Referenzen auf andere Objekte (z. B. von <code>Class<\/code>-Objekten auf Strings). Dies hat den Vorteil, dass die Ahead-of-Time-Cache-Datei direkt vom Dateisystem in den Heap gemappt werden kann \u2013 und das geschieht nahezu ohne Zeitverlust, wenn die Ahead-of-Time-Cache-Datei im Dateisystem-Cache liegt.<\/p>\n\n\n\n<p>Allerdings kann sich die Bin\u00e4rdarstellung sowohl der Objekt-Header als auch der Referenzen von Garbage Collector zu Garbage Collector oder abh\u00e4ngig von VM-Optionen unterscheiden: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bei <a href=\"https:\/\/www.happycoders.eu\/de\/java\/compressed-oops\/\">Compressed OOPs<\/a> (Standard bei Heaps bis maximal 32 GB) sind die Referenzen 32 Bit lang.<\/li>\n\n\n\n<li>Ohne Compressed OOPs (bei einem Heap gr\u00f6\u00dfer als 32 GB oder mit der VM-Option <code>-XX:-UseCompressedOOPs<\/code>) sind sie 64 Bit lang.<\/li>\n\n\n\n<li>ZGC verwendet einige Bits der Referenzen f\u00fcr Metadaten.<\/li>\n\n\n\n<li>Durch die Aktivierung von <a href=\"https:\/\/www.happycoders.eu\/de\/java\/compact-object-headers\/\">Compact Object Headers<\/a> (<code>-XX:+UseCompactObjectHeaders<\/code>) oder die Deaktivierung von <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/\">Compressed Class Pointers<\/a> (deprecated seit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-25-features\/#the-usecompressedclasspointers-option-is-deprecated\">Java 25<\/a>) \u00e4ndert sich das Bin\u00e4rformat des Headers. <\/li>\n<\/ul>\n\n\n\n<p>Deshalb konnte bisher ein Ahead-of-Time-Cache, der mit dem G1, dem Serial GC oder dem Parallel GC erzeugt wurde, nicht von Anwendungen gelesen werden, die den ZGC nutzen \u2013 und vice versa. Ebenso konnte ein Cache, der mit aktivierten Compressed OOPs oder Compact Object Headers erzeugt wurde, nicht von einer Anwendung gelesen werden, bei denen Compressed OOPs oder Compact Object Headers ausgeschaltet sind \u2013 und vice versa. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">GC-unabh\u00e4ngiger Ahead-of-Time-Cache<\/h4>\n\n\n\n<p>Um den Ahead-of-Time-Cache flexibler nutzen zu k\u00f6nnen, k\u00f6nnen wir ab Java 26 einen GC-unabh\u00e4ngigen Ahead-of-Time-Cache erzeugen. Dabei werden die Objekte in der Cache-Datei \u00fcber ihren Index innerhalb des Caches referenziert. Die Cache-Datei kann so nicht mehr direkt in den Heap gemappt werden. Stattdessen  werden die Objekte nach und nach aus der Datei gelesen und dann im GC-spezifischen Format auf dem Heap gespeichert und dort korrekt verlinkt \u2013 oder anders ausgedr\u00fcckt: Sie werden aus der Cache-Datei in den Heap <em>gestreamt<\/em>.<\/p>\n\n\n\n<p>Das GC-unabh\u00e4ngige Format (auch \u201eStreamable Objects\u201c genannt) wird verwendet, wenn im Trainingslauf...<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ZGC verwendet wurde \u2013 oder<\/li>\n\n\n\n<li>Compressed OOPs mit <code>-XX:-CompressedOops<\/code> deaktiviert wurden \u2013 oder<\/li>\n\n\n\n<li>der Heap gr\u00f6\u00dfer war als 32 GB \u2013 oder<\/li>\n\n\n\n<li>die VM-Option <code>-XX:+AOTStreamableObjects<\/code> angegeben wurde.<\/li>\n<\/ul>\n\n\n\n<p>Wenn hingegen eine Anwendung mit dem G1, dem Serial GC oder dem Parallel GC und einem Heap von maximal 32 GB gestartet wurde, wird das bisherige, GC-spezifische Format verwendet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"http-3-for-the-http-client-api-jep-517\">HTTP\/3 for the HTTP Client API \u2013 JEP 517<\/h2>\n\n\n\n<p>Das n\u00e4chste Feature wird bereits durch die \u00dcberschrift vollst\u00e4ndig erkl\u00e4rt: Die <em>HttpClient<\/em>-API unterst\u00fctzt ab Java 26 Version 3 des HTTP-Protokolls (eingef\u00fchrt im Jahr 2022).<\/p>\n\n\n\n<p>Mit der <em>HttpClient<\/em>-API k\u00f6nntest du z. B. wie folgt den Inhalt meiner Homepage laden und in einem String speichern:<\/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\">HttpClient client = HttpClient.newHttpClient();\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(<span class=\"hljs-string\">\"https:\/\/www.happycoders.eu\/\"<\/span>))\n    .build();\n\nHttpResponse&lt;String&gt; response =\n    client.send(request, BodyHandlers.ofString());\n\nString responseBody = response.body();<\/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>Standardm\u00e4\u00dfig wurde hier bisher HTTP\/2 verwendet \u2013 und daran \u00e4ndert sich auch mit Java 26 nichts, da erst ca. ein Drittel aller Webseiten HTTP\/3 unterst\u00fctzen.<\/p>\n\n\n\n<p>Du kannst nun allerdings HTTP\/3 explizit wie folgt aktivieren:<\/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\">HttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(<span class=\"hljs-string\">\"https:\/\/www.happycoders.eu\/\"<\/span>))\n    .version(HttpClient.Version.HTTP_3) <span class=\"hljs-comment\">\/\/ \u2190 Try to use HTTP\/3<\/span>\n    .build();<\/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> Somit wird versucht mit dem Server \u00fcber HTTP\/3 zu kommunizieren. Sollte der Server kein HTTP\/3 unterst\u00fctzen, wird transparent auf HTTP\/2 umgeschaltet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"g1-gc-improve-throughput-by-reducing-synchronization-jep-522\">G1 GC: Improve Throughput by Reducing Synchronization \u2013 JEP 522<\/h2>\n\n\n\n<p><em>G1<\/em> ist der Standard-Garbage-Collector der JVM \u2013 er bietet ein ausgewogenes Verh\u00e4ltnis aus hohem Durchsatz und kurzen Latenzen (im Gegensatz dazu sind der <em>Serial GC<\/em> und der <em>Parallel GC<\/em> auf h\u00f6chstm\u00f6glichen Durchsatz ausgelegt und <em>ZGC<\/em> und <em>Shenandoah<\/em> auf niedrigstm\u00f6gliche Latenzen).<\/p>\n\n\n\n<p>Wenn der Garbage Collector ein Objekt verschiebt, dann muss er auch alle Referenzen <em>auf<\/em> dieses Objekt anpassen. Daf\u00fcr den gesamten Heap zu scannen w\u00e4re sehr ineffizient. Daher scannt G1 nur die Objekte <em>innerhalb<\/em> einer Region (zur Erinnerung: G1 teilt den Heap in ca. 2.048 Regionen auf) \u2013 Referenzen <em>von einer Region in eine andere<\/em> hingegen werden in einer separaten, effizienten Datenstruktur namens <em>Card Table<\/em> gespeichert. Diese kann G1 besonders schnell durchsuchen. <\/p>\n\n\n\n<p>Wie erf\u00e4hrt G1, dass der Anwendungscode eine Referenz von einem Objekt auf ein anderes gesetzt hat, welche zus\u00e4tzlich in der Card Table gespeichert werden muss? Durch sogenannte <em>Write Barriers<\/em>: kurze St\u00fccke von Maschinencode, die G1 beim Start einer Anwendung in den Code einwebt.<\/p>\n\n\n\n<p>Damit das Scannen der Card Table nach dem Verschieben eines Objekts m\u00f6glichst schnell erfolgt, optimiert G1 die Card Table kontinuierlich im Hintergrund. Da G1 parallel zur Anwendung l\u00e4uft, muss der Zugriff auf die Card Table von den Anwendungsthreads \u00fcber die Write Barriers und der Zugriff durch den Optimierungsthread synchronisiert werden. Das wiederum stellt einen nicht unerheblichen Overhead dar.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Reduzierung des Synchronisations-Overheads in Java 26<\/h4>\n\n\n\n<p>Deshalb wird G1 in Java 26 wie folgt optimiert:<\/p>\n\n\n\n<p>Es wird eine zweite Card Table eingef\u00fchrt. W\u00e4hrend die Anwendungsthreads auf eine dieser zwei Card Tables zugreifen, optimiert der Optimierungsthread die jeweils andere. Sobald eine Card Table durch die Anwendungsthreads so stark modifiziert wurde, dass die Zeit f\u00fcr das Scannen dieser Card Table eine gewisse Grenze \u00fcberschreitet, werden die Card Tables getauscht. Der Anwendungsthread greift dann auf die zuvor optimierte Card Table zu, w\u00e4hrend der Optimierungsthread die schwerf\u00e4llig gewordene Card Table wieder optimiert.<\/p>\n\n\n\n<p>Der Optimierungsthread muss somit nicht mit der parallel laufenden Anwendung synchronisiert werden. Der so reduzierte Synchronisationsoverhead kann zu einer Erh\u00f6hung des Gesamtdurchsatzes um 5 bis 15 % f\u00fchren. Die Kosten daf\u00fcr sind minimal: eine Card Table belegt 0,2 % des Heaps \u2013 entsprechend werden bei gleichbleibender Heap-Gr\u00f6\u00dfe lediglich 0,2 % mehr nativer Arbeitsspeicher ben\u00f6tigt.<\/p>\n\n\n\n<p>Diese Optimierung greift nach einem Upgrade auf Java 26 ohne jegliche Code\u00e4nderung oder Anpassung von VM-Parametern.<\/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=\"wiedervorgelegte-preview-und-incubator-features\">Wiedervorgelegte Preview- und Incubator-Features<\/h2>\n\n\n\n<p>Keines der f\u00fcnf Features, die sich in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-25-features\/#wiedervorgelegte-preview-und-incubator-features\">Java 25<\/a> im Preview- bzw. Incubator-Stadium befanden, wurde in Java 26 wurde finalisiert. Alle f\u00fcnf Features wurden mit kleinen oder gr\u00f6\u00dferen \u00c4nderungen wiedervorgelegt. In den folgenden Abschnitten werden die Features mit Fokus auf die \u00c4nderungen gegen\u00fcber Java 25 beschrieben.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"pem-encodings-of-cryptographic-objects-second-preview-jep-524\">PEM Encodings of Cryptographic Objects (Second Preview) \u2013 JEP 524<\/h3>\n\n\n\n<p>PEM steht f\u00fcr Privacy-Enhanced Mail und stellt ein Kodierungsschema f\u00fcr kryptografische Objekte dar. Du hast sicher schon mal PEM-kodierte Objekte gesehen \u2013 wie z. B. das folgende PEM-kodierte kryptografische Zertifikat:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">-----BEGIN CERTIFICATE-----\nMIIDtzCCAz2gAwIBAgISBUCeYELtjMmr4FAIqHapebbFMAoGCCqGSM49BAMDMDIx\nCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF\n. . .\nDBeMde1YpWNXpF9+B\/OMKgn7RgXRj5b2QpBCnFsP92T4cK\/Nn+xFIjYCMCCx4E79\ntoSQBlYnNHv0eXnWkI8TmXsU\/A6rU4Gxdr9GbGixgRJvkw0C6zjL\/lH2Vg==\n-----END CERTIFICATE-----<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><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>PEM-kodierte Objekte in Java zu schreiben oder zu lesen war bisher \u00e4u\u00dferst kompliziert und erforderte \u00fcber ein Dutzend Zeilen Code. Das folgende Beispiel zeigt, was man alles schreiben musste, um einen PEM-kodierten privaten Schl\u00fcssel in Java zu lesen:<\/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\">String encryptedPrivateKeyPemEncoded = . . .\nString passphrase = . . .\n\nString encryptedPrivateKeyBase64Encoded = encryptedPrivateKeyPemEncoded\n    .replace(<span class=\"hljs-string\">\"-----BEGIN ENCRYPTED PRIVATE KEY-----\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n    .replace(<span class=\"hljs-string\">\"-----END ENCRYPTED PRIVATE KEY-----\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n    .replaceAll(<span class=\"hljs-string\">\"&#091;\\\\r\\\\n]\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>);\n\nBase64.Decoder decoder = Base64.getDecoder();\n<span class=\"hljs-keyword\">byte<\/span>&#091;] encryptedPrivateKeyBytes = decoder.decode(encryptedPrivateKeyBase64Encoded);\nEncryptedPrivateKeyInfo encryptedPrivateKeyInfo =\n    <span class=\"hljs-keyword\">new<\/span> EncryptedPrivateKeyInfo(encryptedPrivateKeyBytes);\n\nString algorithmName = encryptedPrivateKeyInfo.getAlgName();\nSecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithmName);\n\nPBEKeySpec pbeKeySpec = <span class=\"hljs-keyword\">new<\/span> PBEKeySpec(passphrase.toCharArray());\nKey pbeKey = secretKeyFactory.generateSecret(pbeKeySpec);\n\nCipher cipher = Cipher.getInstance(algorithmName);\nAlgorithmParameters algParams = encryptedPrivateKeyInfo.getAlgParameters();\ncipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);\n\nKeyFactory rsaKeyFactory = KeyFactory.getInstance(<span class=\"hljs-string\">\"RSA\"<\/span>);\nKeySpec keySpec = encryptedPrivateKeyInfo.getKeySpec(cipher);\nPrivateKey privateKey = rsaKeyFactory.generatePrivate(keySpec);<\/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>In Java 25 wurde als Preview-Feature eine eigene PEM-API eingef\u00fchrt, die den Umgang mit PEM-kodierten Objekten deutlich vereinfachen soll. Das Lesen des verschl\u00fcsselten Private Keys ist so mit nur wenigen Zeilen Code m\u00f6glich (oder nur einer, wenn man alles in eine Zeile schreibt):<\/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\">PrivateKey privateKey = PEMDecoder.of()\n    .withDecryption(passphrase.toCharArray())\n    .decode(encryptedPrivateKeyPemEncoded, PrivateKey<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>)<\/span>;<\/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>Neben dem oben gezeigten <code>PEMDecoder<\/code> gibt es einen entsprechenden <code>PEMEncoder<\/code> mit einer <code>encode()<\/code>-Methode.<\/p>\n\n\n\n<p>In Java 26 bleibt die grunds\u00e4tzliche Funktionsweise dieser API gleich \u2013 es wurden nur einige Details ver\u00e4ndert und der Funktionsumfang etwas erh\u00f6ht:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Es wurden einige Klassen und Methoden umbenannt sowie einige Methoden hinzugef\u00fcgt (von diesen \u00c4nderungen war das simple Beispiel oben nicht betroffen).<\/li>\n\n\n\n<li>Es wurden einige Exceptions angepasst.<\/li>\n\n\n\n<li>Zus\u00e4tzlich zu den bisherigen kryptografischen Objekten k\u00f6nnen nun auch Schl\u00fcsselpaare sowie PKCS#8-kodierte Schl\u00fcssel kodiert und dekodiert werden. <\/li>\n<\/ul>\n\n\n\n<p>Mehr Details zur neuen API und zu diesen \u00c4nderungen findest du in <a href=\"https:\/\/openjdk.org\/jeps\/524\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 524<\/a>. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"structured-concurrency-sixth-preview-jep-525\">Structured Concurrency (Sixth Preview) \u2013 JEP 525<\/h3>\n\n\n\n<p><em>Structured Concurrency<\/em> befindet sich bereits in der sechsten Preview-Runde. Wenn du die API bereits kennst und nur wissen m\u00f6chtest, was sich in Java 26 ge\u00e4ndert hat, kannst du zum Abschnitt <a href=\"#structured-concurrency-aenderungen-in-java-26\">Structured Concurrency \u2013 \u00c4nderungen in Java 26<\/a> springen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Was ist Structured Concurrency?<\/h4>\n\n\n\n<p>Structured Concurrency bedeutet \u2013 im Gegensatz zu <em>Unstructured<\/em> Concurrency und angelehnt an die <a href=\"https:\/\/de.wikipedia.org\/wiki\/Strukturierte_Programmierung\" target=\"_blank\" rel=\"noopener\">Strukturierte Programmierung<\/a> \u2013, dass die Ausf\u00fchrungspfade, die beim Starten nebenl\u00e4ufiger Threads erzeugt werden, an einem einzigen Punkt im Code wieder zusammenlaufen \u2013 und dass garantiert ist, dass an diesem Punkt keine verwaisten Threads mehr ausgef\u00fchrt werden.<\/p>\n\n\n\n<p>Die folgende Grafik soll das demonstrieren. Sie zeigt zudem, dass sich durch Structured Concurrency aufgespannte \u201eScopes\u201c (= die Bereiche, in denen nebenl\u00e4ufige Tasks ausgef\u00fchrt werden) \u2013 ineinander schachteln lassen:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_400\"><img decoding=\"async\" width=\"400\" height=\"400\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-400x400.png\" alt=\"nested structured concurrency\" class=\"wp-image-42208\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-400x400.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-224x224.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-336x336.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-504x504.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-672x672.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-600x600.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency.png 800w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><\/figure>\n<\/div>\n\n\n<p>Dies war bisher \u2013 in eingeschr\u00e4nktem Umfang \u2013 auch mit einem <code>ExecutorService<\/code> und dem Aufruf von <code>close()<\/code> bzw. <code>shutdown()<\/code> und <code>awaitTermination()<\/code> m\u00f6glich. Die Java-API f\u00fcr die Structured Concurrency, <code>StructuredTaskScope<\/code>, bietet jedoch zus\u00e4tzliche M\u00f6glichkeiten, um einen Scope beim Eintritt bestimmter Ereignisse vorzeitig zu beenden und alle noch laufenden Tasks abzubrechen. Das war bei einem <code>ExecutorService<\/code> nur mit einem \u00e4u\u00dferst komplexen und dementsprechend fehleranf\u00e4lligen Orchestrierungsaufwand m\u00f6glich.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">StructuredTaskScope API<\/h4>\n\n\n\n<p>Das folgende Beispiel zeigt, wie sich mit der <code>StructuredTaskScope<\/code>-API mehrere Subtasks parallel starten lassen und dann auf das Ergebnis aller Subtasks gewartet wird. Sollte einer der Subtasks fehlschlagen, werden die noch laufenden Subtasks abgebrochen, und <code>scope.join()<\/code> wirft die Exception, die in dem fehlgeschlagenen Subtask aufgetreten ist.<\/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\">Invoice <span class=\"hljs-title\">createInvoice<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> orderId, <span class=\"hljs-keyword\">int<\/span> customerId, String language)<\/span>\n    <span class=\"hljs-keyword\">throws<\/span> InterruptedException <\/span>{\n  <span class=\"hljs-keyword\">try<\/span> (<span class=\"hljs-keyword\">var<\/span> scope = StructuredTaskScope.open()) {\n    <span class=\"hljs-keyword\">var<\/span> orderTask    = scope.fork(() -&gt; orderService.getOrder(orderId));\n    <span class=\"hljs-keyword\">var<\/span> customerTask = scope.fork(() -&gt; customerService.getCustomer(customerId));\n    <span class=\"hljs-keyword\">var<\/span> templateTask = scope.fork(() -&gt; templateService.getTemplate(language));\n\n    scope.join();\n\n    <span class=\"hljs-keyword\">var<\/span> order    = orderTask.get();\n    <span class=\"hljs-keyword\">var<\/span> customer = customerTask.get();\n    <span class=\"hljs-keyword\">var<\/span> template = templateTask.get();\n\n    <span class=\"hljs-keyword\">return<\/span> Invoice.generate(order, customer, template);\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>Das folgende Beispiel zeigt eine andere (durch <code>Joiner.anySuccessfulOrThrow()<\/code> aktivierte) Strategie: Hier wird nur das Ergebnis <em>eines<\/em> der Subtasks ben\u00f6tigt \u2013 und sobald dieses vorliegt, werden die anderen Subtasks abgebrochen:<\/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-function\">AddressVerificationResponse <span class=\"hljs-title\">verifyAddress<\/span><span class=\"hljs-params\">(Address address)<\/span> <span class=\"hljs-keyword\">throws<\/span> InterruptedException <\/span>{\n  <span class=\"hljs-keyword\">try<\/span> (<span class=\"hljs-keyword\">var<\/span> scope = StructuredTaskScope.open(\n      Joiner.&lt;AddressVerificationResponse&gt;anySuccessfulOrThrow())) {\n\n    scope.fork(() -&gt; verificationService.verifyViaServiceA(address));\n    scope.fork(() -&gt; verificationService.verifyViaServiceB(address));\n    scope.fork(() -&gt; verificationService.verifyViaServiceC(address));\n\n    <span class=\"hljs-keyword\">return<\/span> scope.join();\n  }\n}<\/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>Das hier verwendete <code>Joiner<\/code>-Interface stellt noch weitere Strategien zur Verf\u00fcgung. Welche das sind und wie du dar\u00fcberhinaus eigene Strategien implementieren kannst, erf\u00e4hrst du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/structured-concurrency-structuredtaskscope\/\">Hauptartikel \u00fcber Structured Concurrency in Java<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"structured-concurrency-aenderungen-in-java-26\">Structured Concurrency \u2013 \u00c4nderungen in Java 26<\/h4>\n\n\n\n<p><em>Structured Concurrency<\/em> wurde erstmals in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#structured-concurrency-preview-jep-453\">Java 21<\/a> vorgestellt. In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-25-features\/#structured-concurrency-fifth-preview-jep-505\">Java 25<\/a> wurde die API grundlegend \u00fcberarbeitet (Stichwort: \u201eComposition over Inheritance\u201c). In Java 26 wurden durch <a href=\"https:\/\/openjdk.org\/jeps\/525\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 525<\/a> folgende Erweiterungen und Anpassungen durchgef\u00fchrt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Das <code>Joiner<\/code>-Interface hat neben <code>onFork()<\/code> und <code>onComplete()<\/code> eine zus\u00e4tzliche Methode <code>onTimeout()<\/code> bekommen. Diese wird im Fall eines Timeouts von <code>StructuredTaskScope.join()<\/code> aufgerufen und wirft standardm\u00e4\u00dfig eine <code>TimeoutException<\/code>. Sie kann aber in einem eigenen Joiner \u00fcberschrieben werden, um Timeouts alternativ zu behandeln \u2013 z. B. um einen bestimmten Wert zur\u00fcckzuliefern.<\/li>\n\n\n\n<li>Der durch <code>Joiner.allSuccessfulOrThrow()<\/code> erzeugte Joiner liefert nicht mehr einen Stream von Subtasks zur\u00fcck (die ja ohnehin alle erfolgreich sind), sondern eine Liste der <em>Ergebnisse<\/em> der Subtasks.<\/li>\n\n\n\n<li>Der durch <code>Joiner.allUntil(...)<\/code> erzeugte Joiner liefert statt eines Streams von Subtasks eine <em>Liste<\/em> von Subtasks.<\/li>\n\n\n\n<li>Die Methode <code>Joiner.anySuccessfulResultOrThrow()<\/code> wurde in <code>anySuccessfulOrThrow()<\/code> umbenannt (das Wort <code>Result<\/code> wurde gestrichen, da es auch in den anderen <code>Joiner<\/code>-Factory-Methoden nicht verwendet wird).<\/li>\n\n\n\n<li>Es gibt eine \u00fcberladene <code>StructuredTaskScope.open(...)<\/code>-Methode, mit der die Konfiguration eines Joiners angepasst werden kann. In dieser wurde der Typ f\u00fcr den Konfigurationsparameter von <code>Function&lt;Configuration, Configuration&gt;<\/code> auf <code>UnaryOperator&lt;Configuration&gt;<\/code> ge\u00e4ndert (was letztendlich ja wiederum eine <code>Function&lt;Configuration, Configuration&gt;<\/code> ist).<\/li>\n<\/ul>\n\n\n\n<p>Code der mit Java 25 geschrieben wurde, erfordert also nur kleinere (oder gar keine) Anpassungen, um auf Java 26 zu laufen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"lazy-constants-second-preview-jep-526\">Lazy Constants (Second Preview) \u2013 JEP 526<\/h3>\n\n\n\n<p><em>Lazy Constants<\/em> wurden in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-25-features\/#stable-values-preview-jep-502\">Java 25<\/a> als <em>Stable Values<\/em> eingef\u00fchrt. Wenn du dich mit Stable Values bereits besch\u00e4ftigt hast und nur an den \u00c4nderungen in Java 26 interessiert bist, kannst du zum Abschnitt <a href=\"#lazy-constants-aenderungen-in-java-26\">Lazy Constants \u2013 \u00c4nderungen in Java 26<\/a> springen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Welches Problem wollen wir l\u00f6sen?<\/h4>\n\n\n\n<p>Konstanten \u2013 also unver\u00e4nderliche Werte \u2013 habe viele Vorteile: Sie machen den Code einfacherer und sicherer, da sie nur in <em>einem<\/em> Zustand sein k\u00f6nnen und da auf sie sicher aus mehreren Threads zugegriffen werden kann. Zudem erm\u00f6glichen sie Performance-Optimierungen durch die JVM, z. B. durch (das oben bei finalen Feldern bereits erw\u00e4hnte) <em>Constant Folding<\/em>.<\/p>\n\n\n\n<p>Konstanten k\u00f6nnen bisher nur durch finale Felder definiert werden: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>finale <em>statische Felder<\/em>, die beim Laden einer Klasse initialisiert werden \u2013 oder <\/li>\n\n\n\n<li>finale <em>Instanzfelder<\/em>, die beim Erzeugen eines Objekts initialisiert werden.<\/li>\n<\/ul>\n\n\n\n<p>M\u00f6chte man einen unver\u00e4nderlichen Wert erst bei Bedarf initialisieren, z. B. weil die Initialisierung aufw\u00e4ndig ist, muss man das Konzept der \u201eLazy Initialization\u201c einsetzen. Um Lazy Initialization in Java threadsicher zu gestalten, mussten wir bisher entweder auf das <a href=\"https:\/\/www.happycoders.eu\/de\/java\/double-checked-locking\/\">Double-Checked-Locking-Idiom<\/a> oder das <a href=\"https:\/\/www.happycoders.eu\/de\/java\/initialization-on-demand-holder-idiom\/\">Initialization-on-Demand-Holder-Idiom<\/a> zur\u00fcckgreifen. Wer das schon einmal gemacht hat, wei\u00df, dass sich dabei leicht Fehler einschleichen k\u00f6nnen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Lazy Constants API<\/h4>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-25-features\/#stable-values-preview-jep-502\">Java 25<\/a> wurde die Stable-Values-API vorgestellt, um Lazy Initialization zu vereinfachen. Nach umfangreichem Feedback wurde die API in Java 26 durch <a href=\"https:\/\/openjdk.org\/jeps\/526\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 526<\/a> stark vereinfacht und in <em>Lazy Constants<\/em> umbenannt.<\/p>\n\n\n\n<p>Das folgende Beispiel zeigt, wie wir eine <code>LazyConstant<\/code> definieren, die erst beim ersten Zugriff darauf ein <code>Settings<\/code>-Objekt durch Laden aus einer Datenbank initialisiert:<\/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-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> LazyConstant&lt;Settings&gt; settings =\n    LazyConstant.of(<span class=\"hljs-keyword\">this<\/span>::loadSettingsFromDatabase);\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> Locale <span class=\"hljs-title\">getLocale<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> settings.get().getLocale(); <span class=\"hljs-comment\">\/\/ \u27f5 Here we access the lazy constant<\/span>\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>Nur beim ersten Aufruf von <code>settings.get()<\/code> wird die <code>loadSettingsFromDatabase()<\/code>-Methode aufgerufen. Dabei wird der Wert in dem <code>LazyConstant<\/code>-Objekt gespeichert, und weitere Aufrufe von <code>settings.get()<\/code> liefern diesen gespeicherten Wert zur\u00fcck. Auch die Threadsicherheit wird garantiert: Sollte <code>settings.get()<\/code> aus mehreren Threads gleichzeitig aufgerufen werden, wird <code>loadSettingsFromDatabase()<\/code> dennoch maximal einmal aufgerufen.<\/p>\n\n\n\n<p>Sobald die <code>LazyConstant<\/code> initialisiert ist, wird sie von der JVM als unver\u00e4nderlich interpretiert und der Zugriff darauf durch <em>Constant Folding<\/em> optimiert.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Lazy Lists<\/h4>\n\n\n\n<p>Neben <em>einzelnen<\/em> Lazy Constants k\u00f6nnen wir auch <em>Lazy Lists<\/em> definieren \u2013 Listen, bei denen jedes Element eine Lazy Constant ist. Das folgende Beispiel zeigt eine einfache Lazy List, in der jedes Feld lazily mit der Quadratwurzel des Feld-Indexes initialisiert wird:<\/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-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> List&lt;Double&gt; squareRoots = List.ofLazy(<span class=\"hljs-number\">100<\/span>, Math::sqrt);<\/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>Auch hier erfolgt die Initialisierung erst beim ersten Zugriff \u2013 und zwar separat f\u00fcr jedes Element der Liste, z. B. beim direkten Zugriff mit <code>get(int index)<\/code> \u2013 oder bei der Iteration \u00fcber die Liste. Und auch hier ist die Initialisierung threadsicher, und die Werte werden nach der Initialisierung durch die JVM wie Konstanten behandelt und optimiert.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Lazy Maps<\/h4>\n\n\n\n<p>Auch Maps lassen sich in Zukunft lazily initialisieren. Das folgende Beispiel zeigt eine <em>Lazy Map<\/em>, bei der <code>Locales<\/code> auf <code>ResourceBundles<\/code> gemappt werden:<\/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\">Set&lt;Locale&gt; supportedLocales = getSupportedLocales();\nMap&lt;Locale, ResourceBundle&gt; resourceBundles =\n    Map.ofLazy(supportedLocales, <span class=\"hljs-keyword\">this<\/span>::loadResourceBundle);<\/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>Beim ersten Zugriff auf ein Map-Element f\u00fcr eine bestimmte <code>Locale<\/code> wird das zugeh\u00f6rige <code>ResourceBundle<\/code> \u00fcber <code>loadResourceBundle()<\/code> geladen und dann in der Map als Konstante gespeichert. Genau wie Lazy Constants und Lazy Lists sind auch Lazy Maps threadsicher.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"lazy-constants-aenderungen-in-java-26\">Lazy Constants \u2013 \u00c4nderungen in Java 26<\/h4>\n\n\n\n<p>Neben der offensichtlichen \u00c4nderung \u2013 der Umbenennung in <em>Lazy Constants<\/em> \u2013 wurden in Java 26 folgende Vereinfachungen durchgef\u00fchrt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Low-Level-Methoden wie <code>orElseSet()<\/code>, <code>setOrThrow()<\/code> und <code>trySet()<\/code> wurden entfernt, da diese die API unn\u00f6tig kompliziert machten.<\/li>\n\n\n\n<li><em>Lazy Lists<\/em> und <em>Lazy Maps<\/em> wurden zuvor \u00fcber <code>StableValue.list(...)<\/code> und <code>StableValue.map(...)<\/code> erzeugt. Diese Factory-Methoden wurden in das <code>List<\/code>- bzw. <code>Map<\/code>-Interface verschoben.<\/li>\n\n\n\n<li>Die \u00fcber <code>StableValue.function(...)<\/code> bzw. <code>StableValue.intFunction(...)<\/code> erzeugten <code>Function<\/code>- und <code>IntFunction<\/code>-Implementierungen wurden ersatzlos gestrichen, da sie keinen Mehrwert gegen\u00fcber <em>Lazy Lists<\/em> und <em>Lazy Maps<\/em> darstellten.<\/li>\n\n\n\n<li>Aus Performance-Gr\u00fcnden d\u00fcrfen <em>Lazy Constants<\/em>, <em>Lazy Lists<\/em> und <em>Lazy Maps<\/em> keine <code>null<\/code>-Werte mehr enthalten. Wenn die Berechnungsfunktion <code>null<\/code> zur\u00fcckliefert, wird eine <code>NullPointerException<\/code> geworfen.<\/li>\n<\/ul>\n\n\n\n<p>Solltest du in Java 25 also bereits auf Stable Values gesetzt haben, wird ein umfangreiches Refactoring erforderlich sein.<\/p>\n\n\n\n<p>Mehr Beispiele und Details und findest du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/lazy-constants\/\">Hauptartikel \u00fcber Lazy Constants<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vector-api-eleventh-incubator-jep-529\">Vector API (Eleventh Incubator) \u2013 JEP 529<\/h3>\n\n\n\n<p>Und nun kommen wir \u2013 zum mittlerweile elften Mal \u2013 zur Vector API.<\/p>\n\n\n\n<p>Mit der Vector API lassen sich mathematische Vektoroperationen mit den Vektor-Instruktionss\u00e4tzen moderner CPUs (wie <a href=\"https:\/\/de.wikipedia.org\/wiki\/Streaming_SIMD_Extensions\" target=\"_blank\" rel=\"noopener\">SSE<\/a> und <a href=\"https:\/\/de.wikipedia.org\/wiki\/Advanced_Vector_Extensions\" target=\"_blank\" rel=\"noopener\">AVX<\/a>) besonders effizient berechnen \u2013 z. B. eine Vektor-Addition wie die folgende:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_400\"><img decoding=\"async\" width=\"400\" height=\"91\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-400x91.png\" alt=\"java vector addition\" class=\"wp-image-25531\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-400x91.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-224x51.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-336x76.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-504x115.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-672x153.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-600x137.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition.png 800w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><figcaption class=\"wp-element-caption\">Beispiel einer Vektoraddition<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Als Java-Code w\u00fcrde diese Operation wie folgt implementiert werden, wobei <code>a<\/code> und <code>b<\/code> die Eingabe-Vektoren sind und <code>c<\/code> der Ausgabe-Vektor:<\/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-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> VectorSpecies&lt;Float&gt; SPECIES = FloatVector.SPECIES_PREFERRED;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">addVectors<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">float<\/span>&#091;] a, <span class=\"hljs-keyword\">float<\/span>&#091;] b, <span class=\"hljs-keyword\">float<\/span>&#091;] c)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">int<\/span> i = <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-keyword\">int<\/span> upperBound = SPECIES.loopBound(a.length);\n  <span class=\"hljs-keyword\">for<\/span> (; i &lt; upperBound; i += SPECIES.length()) {\n    <span class=\"hljs-keyword\">var<\/span> va = FloatVector.fromArray(SPECIES, a, i);\n    <span class=\"hljs-keyword\">var<\/span> vb = FloatVector.fromArray(SPECIES, b, i);\n    <span class=\"hljs-keyword\">var<\/span> vc = va.add(vb);\n    vc.intoArray(c, i);\n  }\n  <span class=\"hljs-keyword\">for<\/span> (; i &lt; a.length; i++) {\n    c&#091;i] = a&#091;i] + b&#091;i];\n  }\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<p>Hier ist aktuell noch ziemlich viel Boilerplate notwendig f\u00fcr so eine einfache Operation:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u00dcber <code>SPECIES.length()<\/code> wird abgefragt, wie viele Vektor-Elemente in einem CPU-Zyklus gleichzeitig verarbeitet werden k\u00f6nnen.<\/li>\n\n\n\n<li><code>SPECIES.loopBound(...)<\/code> berechnet, in wie viele vollst\u00e4ndige Teilvektoren dieser L\u00e4nge der Ausgangsvektor aufgesplittet werden kann. <\/li>\n\n\n\n<li>\u00dcber die erste Schleife werden alle Teilvektoren addiert.<\/li>\n\n\n\n<li>Wenn die L\u00e4nge des Ausgangsvektors kein Vielfaches der Teilvektorenl\u00e4nge ist, verbleibt ein Rest.  Dessen Elemente werden \u00fcber die zweite Schleife einzeln addiert.<\/li>\n<\/ul>\n\n\n\n<p>Ich bin gespannt, ob die API noch vereinfacht wird, nachdem sie das Preview-Stadium erreicht hat.<\/p>\n\n\n\n<p>Dazu m\u00fcssen wir uns allerdings noch gedulden, bis der ersten JEP aus <a href=\"https:\/\/openjdk.org\/projects\/valhalla\/\" target=\"_blank\" rel=\"noopener\">Project Valhalla<\/a> \u2013 <a href=\"https:\/\/openjdk.org\/jeps\/401\" target=\"_blank\" rel=\"noopener\">JEP 401: Value Classes and Objects<\/a> das Preview-Stadium erreicht hat. Denn die <code>Vector<\/code>-Klasse soll von Anfang an eine <a href=\"https:\/\/openjdk.org\/projects\/valhalla\/value-objects\" target=\"_blank\" rel=\"noopener\">Value Class<\/a> sein \u2013 also eine Klasse, deren Objekte ohne Identit\u00e4t auskommen werden. <\/p>\n\n\n\n<p>Wann wird es soweit sein? Brian Goetz, Language Architekt bei Oracle, beantwortet die Frage nach dem Erscheinungsdatum von Project Valhalla seit Jahren konsequent mit: \u201eIt\u2019s ready when it\u2019s ready\u201c \u2013 eine konkretere Aussage lie\u00df er sich bisher nicht entlocken. Am 10. Oktober 2025 wurde der Java-Community endlich ein erstes <a href=\"https:\/\/jdk.java.net\/valhalla\/\" target=\"_blank\" rel=\"noopener\">Early-Access Build von Projekt Valhalla<\/a> zur Verf\u00fcgung gestellt.<\/p>\n\n\n\n<p>Die elfte Incubator-Version der Vector API wird in <a href=\"https:\/\/openjdk.org\/jeps\/529\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 529<\/a> beschrieben: Es gibt keine substanziellen \u00c4nderungen gegen\u00fcber der vorherigen Version.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"primitive-types-in-patterns-instanceof-and-switch-fourth-preview-jep-530\">Primitive Types in Patterns, instanceof, and switch (Fourth Preview) \u2013 JEP 530<\/h3>\n\n\n\n<p>Pattern Matching mit primitiven Typen wurde erstmals in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#primitive-types-in-patterns-instanceof-and-switch-preview-jep-455\">Java 23<\/a> als Preview-Feature vorgestellt. Seither gab es keine grundlegenden \u00c4nderungen. Wenn du mit dem Feature bereits vertraut bist und dich f\u00fcr die kleinen Verfeinerungen in Java 26 interessierst, springe gerne zum Abschnitt <a href=\"#primitive-types-in-patterns-aenderungen-in-java-26\">Primitive Types in Patterns \u2013 \u00c4nderungen in Java 26<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Pattern Matching und switch mit primitiven Typen \u2013 Status Quo<\/h4>\n\n\n\n<p>Pattern Matching ist bisher auf Referenztypen beschr\u00e4nkt, beispielsweise wie folgt: <\/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\">Object obj = . . .\n<span class=\"hljs-keyword\">switch<\/span> (obj) {\n  <span class=\"hljs-keyword\">case<\/span> String s when s.length() &gt;= <span class=\"hljs-number\">5<\/span> -&gt; IO.println(s.toUpperCase());\n  <span class=\"hljs-keyword\">case<\/span> Integer i                     -&gt; IO.println(i * i);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">null<\/span>, <span class=\"hljs-keyword\">default<\/span>                 -&gt; IO.println(obj);\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>Ein <code>switch<\/code> \u00fcber primitive Typen ist zwar m\u00f6glich \u2013 allerdings nur mit <code>byte<\/code>, <code>short<\/code>, <code>char<\/code> und <code>int<\/code> \u2013 und in den <code>case<\/code>-Labels sind nur Konstanten erlaubt:<\/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-keyword\">int<\/span> code = . . .\n<span class=\"hljs-keyword\">switch<\/span> (code) {\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-number\">200<\/span> -&gt; IO.println(<span class=\"hljs-string\">\"OK\"<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-number\">404<\/span> -&gt; IO.println(<span class=\"hljs-string\">\"Not Found\"<\/span>);\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<h4 class=\"wp-block-heading\">Pattern Matching und switch mit primitiven Typen \u2013 Was wird sich \u00e4ndern?<\/h4>\n\n\n\n<p>In Zukunft sollen im <code>switch<\/code> alle primitiven Typen erlaubt sein, also auch <code>long<\/code>, <code>double<\/code>, <code>float<\/code> und sogar <code>boolean<\/code>. Und in den <code>case<\/code>-Labels sollen auch Patterns erlaubt sein. Damit k\u00f6nnten wir dann z. B. einen <code>int<\/code>-Wert auf bestimmte Zahlenbereiche pr\u00fcfen:<\/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\">int<\/span> code = . . .\n<span class=\"hljs-keyword\">switch<\/span> (code) {\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">int<\/span> i when i &gt;= <span class=\"hljs-number\">100<\/span> &amp;&amp; i &lt; <span class=\"hljs-number\">200<\/span> -&gt; IO.println(<span class=\"hljs-string\">\"information\"<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">int<\/span> i when i &gt;= <span class=\"hljs-number\">200<\/span> &amp;&amp; i &lt; <span class=\"hljs-number\">300<\/span> -&gt; IO.println(<span class=\"hljs-string\">\"success\"<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">int<\/span> i when i &gt;= <span class=\"hljs-number\">300<\/span> &amp;&amp; i &lt; <span class=\"hljs-number\">400<\/span> -&gt; IO.println(<span class=\"hljs-string\">\"redirection\"<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">int<\/span> i when i &gt;= <span class=\"hljs-number\">400<\/span> &amp;&amp; i &lt; <span class=\"hljs-number\">500<\/span> -&gt; IO.println(<span class=\"hljs-string\">\"client error\"<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">int<\/span> i when i &gt;= <span class=\"hljs-number\">500<\/span> &amp;&amp; i &lt; <span class=\"hljs-number\">600<\/span> -&gt; IO.println(<span class=\"hljs-string\">\"server error\"<\/span>);\n  <span class=\"hljs-keyword\">default<\/span> -&gt; <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException();\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>Pattern mit Referenztypen matchen auch auf abgeleitete Typen, z. B. w\u00fcrde ein <code>case Number n<\/code> auch auf ein Objekt vom Typ <code>Integer<\/code> matchen. Bei primitiven Typen gibt es keine Vererbung \u2013 daher haben sich die JDK-Developer hier etwas anderes \u00fcberlegt:<\/p>\n\n\n\n<p>Wir k\u00f6nnen in Zukunft mit <code>switch<\/code> (und genauso mit <code>instanceof<\/code>) pr\u00fcfen, ob sich der Wert einer primitiven Variablen ohne Pr\u00e4zisionsverlust mit einem anderen primitiven Typen darstellen l\u00e4sst:<\/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-keyword\">double<\/span> value = . . .\n<span class=\"hljs-keyword\">switch<\/span> (value) {\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">byte<\/span>   b -&gt; IO.println(value + <span class=\"hljs-string\">\" instanceof byte:   \"<\/span> + b);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">short<\/span>  s -&gt; IO.println(value + <span class=\"hljs-string\">\" instanceof short:  \"<\/span> + s);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">char<\/span>   c -&gt; IO.println(value + <span class=\"hljs-string\">\" instanceof char:   \"<\/span> + c);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">int<\/span>    i -&gt; IO.println(value + <span class=\"hljs-string\">\" instanceof int:    \"<\/span> + i);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">long<\/span>   l -&gt; IO.println(value + <span class=\"hljs-string\">\" instanceof long:   \"<\/span> + l);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">float<\/span>  f -&gt; IO.println(value + <span class=\"hljs-string\">\" instanceof float:  \"<\/span> + f);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">double<\/span> d -&gt; IO.println(value + <span class=\"hljs-string\">\" instanceof double: \"<\/span> + d);\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>Wenn hier <code>value<\/code> z. B. 42 w\u00e4re, dann w\u00fcrde das Pattern <code>byte b<\/code> matchen, da sich 42 auch in einem <code>byte<\/code> speichern l\u00e4sst. W\u00e4re <code>value<\/code> z. B. 50.000,  dann w\u00fcrde das Pattern <code>char c<\/code> matchen. F\u00fcr 65.000 w\u00fcrde <code>int i<\/code> matchen, f\u00fcr 0,5 <code>float f<\/code> und f\u00fcr 0,7 erst <code>double d<\/code>.<\/p>\n\n\n\n<p>Auch bei primitiven Typen gilt das Dominanzprinzip: Die Reihenfolge der <code>case<\/code>-Labels im vorherigen Beispiel darf nicht ver\u00e4ndert werden, da dann einzelne <code>case<\/code>-Labels nicht mehr erreichbar w\u00e4ren. Beispielsweise d\u00fcrfte das Pattern <code>int i<\/code> nicht vor <code>byte b<\/code> erscheinen, da jedes m\u00f6gliche Byte bereits auf <code>int i<\/code> matchen w\u00fcrde.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"primitive-types-in-patterns-aenderungen-in-java-26\">Primitive Types in Patterns \u2013 \u00c4nderungen in Java 26<\/h4>\n\n\n\n<p>Durch <a href=\"https:\/\/openjdk.org\/jeps\/530\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 530<\/a> wurde in Java 26 haupts\u00e4chlich die Dominanzpr\u00fcfung verbessert. Der folgende Code beispielsweise l\u00e4sst sich mit Java 25 noch fehlerfrei compilieren:<\/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-keyword\">int<\/span> i1 = . . .\n<span class=\"hljs-keyword\">switch<\/span> (i1) {\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">float<\/span> f -&gt; {}\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-number\">16_777_216<\/span> -&gt; {}\n  <span class=\"hljs-keyword\">default<\/span> -&gt; {}\n}\n\n<span class=\"hljs-keyword\">int<\/span> i2 = . . .\n<span class=\"hljs-keyword\">switch<\/span> (i2) {\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">int<\/span> _ -&gt; {}\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">float<\/span> _ -&gt; {}\n}\n\n<span class=\"hljs-keyword\">byte<\/span> b = . . .\n<span class=\"hljs-keyword\">switch<\/span> (b) {\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">short<\/span> s -&gt; {}\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-number\">42<\/span> -&gt; {}\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>In Java 26 hingegen werden alle drei <code>switch<\/code>-Statements mit Compilerfehlern quittiert:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Im ersten <code>switch<\/code> kann die Konstante 16.777.216 niemals matchen, da diese Zahl auch pr\u00e4zise mit einem <code>float<\/code> dargestellt werden kann und somit die Konstante durch das Pattern <code>float f<\/code> dominiert wird.<\/li>\n\n\n\n<li>Im zweiten <code>switch<\/code> kann das Pattern <code>float f<\/code> niemals matchen, da jeder Wert, den <code>i2<\/code> annehmen kann, brereits durch das Pattern <code>int _<\/code> gematcht wird.<\/li>\n\n\n\n<li>Im dritten <code>switch<\/code> kann die Konsante 42 niemals matchen, da die 42 auch in einem <code>short<\/code> gespeichert werden kann und somit die Konstante durch das Pattern <code>short s<\/code> dominiert wird.<\/li>\n<\/ul>\n\n\n\n<p>Neben der verbesserten Dominanzpr\u00fcfung gibt es in Java 26 keine \u00c4nderungen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"deprecations-und-loeschungen\">Deprecations und L\u00f6schungen<\/h2>\n\n\n\n<p>In Java 26 wurden die Applet-API sowie die Methode <code>Thread.stop()<\/code> entfernt. Details findest du in den folgenden zwei Abschnitten.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"remove-the-applet-api-jep-504\">Remove the Applet API \u2013 JEP 504<\/h3>\n\n\n\n<p>Die Applet-API sowie der Security Manager, der f\u00fcr die Absicherung von Applets verantwortlich war, wurden in Java 9 im Jahr 2017 als <em>deprecated<\/em> markiert, da Applets zu der Zeit von keinem modernen Webbrowser mehr unterst\u00fctzt wurden. In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-17-features\/#deprecate-the-applet-api-for-removal\">Java 17<\/a> wurden Applet-API und Security Manager als <em>deprecated for removal<\/em> markiert.<\/p>\n\n\n\n<p>Der Security Manager wurde in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#permanently-disable-the-security-manager-jep-486\">Java 24<\/a> deaktiviert.<\/p>\n\n\n\n<p>In Java 26 wurde nun die Applet-API \u2013 d. h. alle Klassen des Pakets <code>java.applet<\/code> sowie einige weitere, wie <code>java.beans.AppletInitializer<\/code> und <code>javax.swing.JApplet<\/code> \u2013 via <a href=\"https:\/\/openjdk.org\/jeps\/504\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 504<\/a> vollst\u00e4ndig entfernt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"thread-stop-is-removed\">Thread.stop is removed<\/h3>\n\n\n\n<p><code>Thread.stop()<\/code> wurde bereits in Java 1.2 \u2013 im Dezember 1998 \u2013 als <em>deprecated<\/em> markiert, weil es zu inkonsisten Zust\u00e4nden und unvorhersehbarem Verhalten f\u00fchren konnte. In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-18-features\/#terminally-deprecate-thread-stop\">Java 18<\/a> wurde es als <em>deprecated for removal<\/em> markiert, und seit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-20-features\/#thread-stop-changed-to-throw-unsupportedoperationexception\">Java 20<\/a> wirft es eine <code>UnsupportedOperationException<\/code>.<\/p>\n\n\n\n<p>In Java 26 \u2013 also mehr als 27 Jahre nach der Markierung als <em>deprecated<\/em> \u2013 wird die Methode nun vollst\u00e4ndig entfernt.<\/p>\n\n\n\n<p><em>(F\u00fcr diese \u00c4nderung gibt es keinen JEP, sie ist im Bug-Tracker unter <\/em><a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8368226\" target=\"_blank\" rel=\"noopener\">JDK-8368226<\/a><em> registriert.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sonstige-aenderungen-in-java-26\">Sonstige \u00c4nderungen in Java 26<\/h2>\n\n\n\n<p>In diesem Abschnitt findest du eine Auswahl kleinerer \u00c4nderungen aus den Release Notes, f\u00fcr die keine JDK Enhancement Proposals geschrieben wurden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"add-dark-theme-to-api-documentation\">Add Dark Theme to API Documentation<\/h3>\n\n\n\n<p>Dieses Feature ist schnell erkl\u00e4rt: an Java 26 bietet die Javadoc-Dokumentation einen Dark Mode an. Du kannst ihn bereits in der <a href=\"https:\/\/download.java.net\/java\/early_access\/jdk26\/docs\/api\/\" target=\"_blank\" rel=\"noopener\">Early-Access-Dokumentation von 26<\/a> ausprobieren, indem du auf das Sonnen- bzw. Mondsymbol in der Men\u00fcleiste klickst.<\/p>\n\n\n\n<p>Hier ein Eindruck vom neuen Modus: <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"564\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-800x564.jpg\" alt=\"java 26 dark mode.v2\" class=\"wp-image-53941\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-800x564.jpg 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-224x158.jpg 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-336x237.jpg 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-504x355.jpg 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-672x474.jpg 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-400x282.jpg 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-600x423.jpg 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-944x666.jpg 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2-1200x846.jpg 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-dark-mode.v2.jpg 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/figure>\n<\/div>\n\n\n<p><em>(F\u00fcr diese \u00c4nderung gibt es keinen JEP, sie ist im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8342705\" target=\"_blank\" rel=\"noopener\">JDK-8342705<\/a> registriert.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"new-offilechannel-method-in-java-net-http-httprequest-bodypublishers\">New ofFileChannel Method in java.net.http.HttpRequest.BodyPublishers<\/h3>\n\n\n\n<p>Um mit der <code>HttpClient<\/code>-API (verf\u00fcgbar seit <a href=\"https:\/\/www.happycoders.eu\/java\/java-11-features\/#http-client-standard\">Java 11<\/a>) eine Datei zu senden, musste diese bisher komplett in den RAM geladen und als Byte-Array an den <code>HttpRequest<\/code> \u00fcbergeben werden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">byte<\/span>&#091;] fileContent = Files.readAllBytes(Path.of(<span class=\"hljs-string\">\"test.bin\"<\/span>));\n\n<span class=\"hljs-keyword\">try<\/span> (HttpClient client = HttpClient.newHttpClient()) {\n  HttpRequest request =\n      HttpRequest.newBuilder()\n          .uri(URI.create(<span class=\"hljs-string\">\"https:\/\/www.example.com\/upload\"<\/span>))\n          .POST(BodyPublishers.ofByteArray(fileContent))\n          .build();\n\n  HttpResponse&lt;Void&gt; response =\n      client.send(request, HttpResponse.BodyHandlers.discarding());\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><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>Ab Java 26 kann eine Datei (oder ein Teil davon) auch per <code>FileChannel<\/code> in den <code>HttpRequest<\/code> gestreamt werden und muss so nicht mehr zuvor vollst\u00e4ndig im Arbeitsspeicher bereitstehen. Das ist insbesondere bei sehr gro\u00dfen Dateien hilfreich:<\/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-keyword\">try<\/span> (FileChannel fileChannel = \n        FileChannel.open(Path.of(<span class=\"hljs-string\">\"test.bin\"<\/span>), StandardOpenOption.READ);\n    HttpClient client = HttpClient.newHttpClient()) {\n\n  HttpRequest request =\n      HttpRequest.newBuilder()\n          .uri(URI.create(<span class=\"hljs-string\">\"https:\/\/www.example.com\/upload\"<\/span>))\n          .POST(BodyPublishers.ofFileChannel(fileChannel, <span class=\"hljs-number\">0<\/span>, fileChannel.size()))\n          .build();\n\n  HttpResponse&lt;Void&gt; response =\n      client.send(request, HttpResponse.BodyHandlers.discarding());\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><em>(F\u00fcr diese \u00c4nderung gibt es keinen JEP, sie ist im Bug-Tracker unter <\/em><a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8329829\" target=\"_blank\" rel=\"noopener\">JDK-8329829<\/a><em> registriert.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"default-initial-heap-size-is-trimmed-down\">Default initial heap size is trimmed down<\/h3>\n\n\n\n<p>Wenn beim Start einer Java-Anwendung weder mit <code>-Xms<\/code> noch mit <code>-XX:InitialRAMPercentage<\/code> eine minimale Heap-Gr\u00f6\u00dfe angegeben wird, wird der Heap standardm\u00e4\u00dfig auf 1\/64 (= 1,5625 %) des physischen RAMs gesetzt. Heute haben Computer deutlich mehr RAM als noch vor zwanzig Jahren, so dass viele Anwendungen mit einem unn\u00f6tig gro\u00dfen Heap ausgestattet werden. Auf meinem 64-GB-Laptop beispielsweise wird so selbst eine Hello-World-Anwendung mit einem 1-GB-Heap gestartet.<\/p>\n\n\n\n<p>Neben dem unn\u00f6tig belegten RAM kann das auch den Start einer Anwendung sp\u00fcrbar verz\u00f6gern, da der Garbage Collector f\u00fcr den Heap initiale Datenstrukturen anlegen muss, die mit der Heap-Gr\u00f6\u00dfe skalieren.<\/p>\n\n\n\n<p>In Java 26 wird die initiale Heap-Gr\u00f6\u00dfe standardm\u00e4\u00dfig auf 0,2 % ge\u00e4ndert, also 1\/500 des physischen RAMs. Auf meinem 64-GB-Laptop sind das immer noch f\u00fcr viele kleine Anwendungen ausreichende 128 MB.<\/p>\n\n\n\n<p><em>(F\u00fcr diese \u00c4nderung gibt es keinen JEP, sie ist im Bug-Tracker unter <\/em><a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8348278\" target=\"_blank\" rel=\"noopener\">JDK-8348278<\/a><em> registriert.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"virtual-threads-now-unmount-when-waiting-for-another-thread-to-execute-a-class-initializer\">Virtual threads now unmount when waiting for another thread to execute a class initializer<\/h3>\n\n\n\n<p>Unter bestimmten Umst\u00e4nden werden virtuelle Threads an ihren Carrier-Thread \u201egepinnt\u201c, d. h. wenn der virtuelle Thread blockiert, kann dieser nicht von seinem Carrier-Thread (dem Betriebssystem-Thread, auf dem der virtuelle Thread ausgef\u00fchrt wird) geunmounted werden. Somit ist auch der Carrier-Thread blockiert und kann keinen anderen virtuellen Thread ausf\u00fchren.<\/p>\n\n\n\n<p>Bereits in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#synchronize-virtual-threads-without-pinning-jep-491\">Java 24<\/a> wurde das schwerwiegende Problem des Pinnings innerhalb von <code>synchronized<\/code>-Bl\u00f6cken behoben.<\/p>\n\n\n\n<p>Vor Java 26 wurde ein virtueller Thread auch dann gepinnt, wenn er versucht, eine Klasse zu initialisieren, die gerade von einem anderen Thread initialisiert wird. Auch das passiert nun nicht mehr. <\/p>\n\n\n\n<p><em>(F\u00fcr diese \u00c4nderung gibt es keinen JEP, sie ist im Bug-Tracker unter <\/em><a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8369238\" target=\"_blank\" rel=\"noopener\">JDK-8369238<\/a><em> registriert.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"support-for-unicode-17-0\">Support for Unicode 17.0<\/h3>\n\n\n\n<p>Java 26 erh\u00f6ht die Unicode-Unterst\u00fctzung auf Version 17.0.<\/p>\n\n\n\n<p>Warum ist das relevant? Alle zeichenverarbeitenden Klassen wie <code>String<\/code> und <code>Character<\/code> m\u00fcssen in der Lage sein, die in der neuen Unicode-Version eingef\u00fchrten Zeichen und Codebl\u00f6cke zu verarbeiten.<\/p>\n\n\n\n<p><em>(F\u00fcr diese \u00c4nderung gibt es keinen JEP, sie ist im Bug-Tracker unter <\/em><a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8346944\" target=\"_blank\" rel=\"noopener\">JDK-8346944<\/a><em> registriert.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vollstaendige-liste-aller-aenderungen-in-java-26\">Vollst\u00e4ndige Liste aller \u00c4nderungen in Java 26<\/h3>\n\n\n\n<p>In diesem Artikel haben ich alle JDK Enhancement Proposals vorgestellt, die ich Java 26 ausgeliefert wurden, sowie eine Auswahl von \u00c4nderungen aus den Release Notes. Die vollst\u00e4ndige Liste aller \u00c4nderungen findest du in den <a href=\"https:\/\/jdk.java.net\/26\/release-notes\" target=\"_blank\" rel=\"noopener\">Java 26 Release Notes<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"fazit\">Fazit<\/h2>\n\n\n\n<p>Im Vergleich zu den letzten zwei Java-Versionen fallen die \u00c4nderungen in Java 26 sehr \u00fcbersichtlich aus:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Bei der Mutation von finalen Feldern mit Deep Reflection wird nun eine Warnung ausgegeben \u2013 in Zukunft wird eine Exception geworfen.<\/li>\n\n\n\n<li>Das in Java 24 eingef\u00fchrte <em>Ahead-of-Time Class Loading &amp; Linking<\/em> funktioniert nun mit jedem Garbage Collector \u2013 nicht mehr nur mit dem G1.<\/li>\n\n\n\n<li><em>HttpClient<\/em> unterst\u00fctzt nun HTTP\/3.<\/li>\n\n\n\n<li>Der G1 Garbage Collector wurde optimiert, was zu einer Erh\u00f6hung des Durchsatzes f\u00fchrt.<\/li>\n\n\n\n<li>Die Applet-API und <code>Thread.stop()<\/code> wurden entfernt. <\/li>\n\n\n\n<li><em>Stable Values<\/em> wurden in <em>Lazy Constants<\/em> umgenannt \u2013 und die API wurde radikal vereinfacht.<\/li>\n\n\n\n<li>Bei den \u00fcbrigen Features, die sich derzeit im Preview-Stadium befinden, wurden kleinere Verbesserungen vorgenommen.<\/li>\n<\/ul>\n\n\n\n<p>Diverse sonstige \u00c4nderungen runden wie immer das Release ab. Das aktuelle Java 26 Early-Access Release kannst du <a href=\"https:\/\/jdk.java.net\/26\/\" target=\"_blank\" rel=\"noopener\">hier<\/a> herunterladen.<\/p>\n\n\n\n<p>Welche der \u00c4nderungen findest du am spannendsten? Teile deine Meinung in den Kommentaren!<\/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>Die neuen Java 26 Features: Prepare to Make Final Mean Final, Ahead-of-Time Caching mit allen GCs, HTTP\/3, G1 mit besserem Durchsatz und mehr...<\/p>\n","protected":false},"author":1,"featured_media":53998,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"","_seopress_titles_title":"","_seopress_titles_desc":"","_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":39399,"_post_count":0,"footnotes":""},"categories":[64],"tags":[176],"class_list":["post-53935","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java","tag-java-versionen"],"uagb_featured_image_src":{"full":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image.jpg",1770,986,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image.jpg",150,84,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image.jpg",768,428,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image.jpg",1024,570,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-224x125.jpg",224,125,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-504x281.jpg",504,281,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-672x374.jpg",672,374,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-400x223.jpg",400,223,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-600x334.jpg",600,334,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-800x446.jpg",800,446,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-944x526.jpg",944,526,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-1200x668.jpg",1200,668,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image-1770x735.jpg",1770,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-feature-image.jpg",1536,856,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/11\/java-26-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":0,"uagb_excerpt":"Die neuen Java 26 Features: Prepare to Make Final Mean Final, Ahead-of-Time Caching mit allen GCs, HTTP\/3, G1 mit besserem Durchsatz und mehr...","public_identification_id":"aa67c463908946f3b32fabd6d3602e8b","private_identification_id":"8a73b536abb84c27baa6372d88b92097","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/53935","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=53935"}],"version-history":[{"count":10,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/53935\/revisions"}],"predecessor-version":[{"id":54121,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/53935\/revisions\/54121"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/53998"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=53935"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=53935"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=53935"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}