{"id":31297,"date":"2022-09-20T08:30:00","date_gmt":"2022-09-20T06:30:00","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=31297"},"modified":"2025-06-12T08:23:36","modified_gmt":"2025-06-12T06:23:36","slug":"java-19-features","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/java-19-features\/","title":{"rendered":"Java 19 Features (mit Beispielen)"},"content":{"rendered":"\n<p>Java 19 wurde am 20. September 2022 ver\u00f6ffentlicht. Du kannst es <a href=\"https:\/\/jdk.java.net\/19\/\">hier<\/a> herunterladen.<\/p>\n\n\n\n<p>Die spannendste Neuerung sind f\u00fcr mich die <a href=\"#Virtual_Threads_Preview_-_JEP_425\">virtuellen Threads<\/a>, die seit mehreren Jahren im Rahmen von <a rel=\"noopener\" href=\"https:\/\/openjdk.org\/projects\/loom\/\" target=\"_blank\">Project Loom<\/a> entwickelt werden und nun endlich als Preview im JDK enthalten sind.<\/p>\n\n\n\n<p>Virtuelle Threads sind die Voraussetzung f\u00fcr <a href=\"#Structured_Concurrency_Incubator_-_JEP_428\">Structured Concurrency<\/a>, ein weiteres spannendes neues Incubator-Feature in Java 19.<\/p>\n\n\n\n<p>F\u00fcr alle, die auf Nicht-Java-Code (z. B. die C-Standard-Bibliothek) zugreifen wollen, gibt es ebenfalls gute Nachrichten: Die <a href=\"#Foreign_Function_Memory_API_Preview_-_JEP_424\">Foreign Function &amp; Memory API<\/a> hat nach f\u00fcnf Incubator-Runden nun auch das Preview-Stadium erreicht.<\/p>\n\n\n\n<p>Wie immer verwende ich die englischen Bezeichnungen der JEPs.<\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"new-methods-to-create-preallocated-hashmaps\">New Methods to Create Preallocated HashMaps<\/h2>\n\n\n\n<p>Wenn wir eine <code>ArrayList<\/code> f\u00fcr eine vorab bekannte Anzahl an Elementen (z. B. 120) erzeugen wollen, dann k\u00f6nnen wir das seit jeher wie folgt tun:<\/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\">List&lt;String&gt; list = <span class=\"hljs-keyword\">new<\/span> ArrayList&lt;&gt;(<span class=\"hljs-number\">120<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Dadruch wird das der <code>ArrayList<\/code> zugrunde liegende Array direkt f\u00fcr 120 Elemente allokiert und muss nicht mehrfach vergr\u00f6\u00dfert (also neu angelegt und umkopiert) werden, um die 120 Elemente einzuf\u00fcgen.<\/p>\n\n\n\n<p>Ebenso k\u00f6nnen wir seit jeher eine <code>HashMap<\/code> wie folgt erzeugen:<\/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\">Map&lt;String, Integer&gt; map = <span class=\"hljs-keyword\">new<\/span> HashMap&lt;&gt;(<span class=\"hljs-number\">120<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Intuitiv w\u00fcrde man denken, diese <code>HashMap<\/code> biete Platz f\u00fcr 120 Mappings.<\/p>\n\n\n\n<p>Das ist allerdings nicht der Fall!<\/p>\n\n\n\n<p>Denn die <code>HashMap<\/code> wird mit einem Default-Load-Faktor von 0,75 initialisiert. Das bedeutet: Sobald die <code>HashMap<\/code> zu 75 % gef\u00fcllt ist, wird sie mit doppelter Gr\u00f6\u00dfe neu aufgebaut (\"rehashed\"). Dadurch soll sichergestellt werden, dass die Elemente m\u00f6glichst gleichm\u00e4\u00dfig auf die Buckets der <code>HashMap<\/code> verteilt sind und m\u00f6glichst kein Bucket mehr als ein Element enth\u00e4lt.<\/p>\n\n\n\n<p>Die mit einer Kapazit\u00e4t von 120 initialisierte <code>HashMap<\/code> kann also nur 120 \u00d7 0,75 = 90 Mappings aufnehmen.<\/p>\n\n\n\n<p>Um eine <code>HashMap<\/code> f\u00fcr 120 Mappings zu erzeugen, musste man bisher die Kapazit\u00e4t selbst berechnen, indem man die Anzahl der Mappings durch den Load-Faktor teilt: 120 \u00f7 0,75 = 160.<\/p>\n\n\n\n<p>Eine <code>HashMap<\/code> f\u00fcr 120 Mappings musste also wie folgt angelegt werden:<\/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-comment\">\/\/ for 120 mappings: 120 \/ 0.75 = 160<\/span>\nMap&lt;String, Integer&gt; map = <span class=\"hljs-keyword\">new<\/span> HashMap&lt;&gt;(<span class=\"hljs-number\">160<\/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>Java 19 macht uns das einfacher \u2013 wir k\u00f6nnen stattdessen jetzt folgendes schreiben:<\/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\">Map&lt;String, Integer&gt; map = HashMap.newHashMap(<span class=\"hljs-number\">120<\/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>Wenn wir uns den Quellcode der neuen Methoden anschauen, sehen wir, dass im Endeffekt das gleiche passiert, was wir vorher manuell gemacht haben:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> &lt;K, V&gt; <span class=\"hljs-function\">HashMap&lt;K, V&gt; <span class=\"hljs-title\">newHashMap<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> numMappings)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">new<\/span> HashMap&lt;&gt;(calculateHashMapCapacity(numMappings));\n}\n\n<span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">float<\/span> DEFAULT_LOAD_FACTOR = <span class=\"hljs-number\">0.75f<\/span>;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">int<\/span> <span class=\"hljs-title\">calculateHashMapCapacity<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> numMappings)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> (<span class=\"hljs-keyword\">int<\/span>) Math.ceil(numMappings \/ (<span class=\"hljs-keyword\">double<\/span>) DEFAULT_LOAD_FACTOR);\n}\n<\/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>Die <code>newHashMap()<\/code>-Methode wurde ebenfalls in <code>LinkedHashMap<\/code> und <code>WeakHashMap<\/code> eingebaut.<\/p>\n\n\n\n<p>Zu dieser Erweiterung gibt es kein JDK Enhancement Proposal.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"preview-und-incubator-features\">Preview- und Incubator-Features<\/h2>\n\n\n\n<p>Java 19 liefert uns insgesamt sechs Preview- und Incubator-Features, also Features, die noch nicht fertiggestellt sind, die von der Entwickler-Community aber bereits getestet werden k\u00f6nnen. Das Feedback der Community geht in der Regel in die Weiterentwicklung und Fertigstellung dieser Features ein.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"pattern-matching-for-switch-third-preview-jep-427\">Pattern Matching for switch (Third Preview) \u2013 JEP 427<\/h3>\n\n\n\n<p>Fangen wir mit einem Feature an, das bereits zwei Preview-Runden hinter sich hat. Das in <a href=\"\/de\/java\/java-17-features\/#Pattern_Matching_for_switch_Preview\">Java 17<\/a> erstmals vorgestellte \"Pattern Matching for switch\" erlaubte uns Code wie den folgenden zu schreiben:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">switch<\/span> (obj) {\n  <span class=\"hljs-keyword\">case<\/span> String s &amp;&amp; s.length() &gt; <span class=\"hljs-number\">5<\/span> -&gt; System.out.println(s.toUpperCase());\n  <span class=\"hljs-keyword\">case<\/span> String s                   -&gt; System.out.println(s.toLowerCase());\n\n  <span class=\"hljs-keyword\">case<\/span> Integer i                  -&gt; System.out.println(i * i);\n\n  <span class=\"hljs-keyword\">default<\/span> -&gt; {}\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<p>Wir k\u00f6nnen damit innerhalb eines <code>switch<\/code>-Statements pr\u00fcfen, ob ein Objekt von einer bestimmten Klasse ist und ob es ggf. weitere Eigenschaften (wie im Beispiel: l\u00e4nger als 5 Zeichen) aufweist.<\/p>\n\n\n\n<p>In Java 19 wurde mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/427\" target=\"_blank\">JDK Enhancement Proposal 427<\/a> die Syntax des sogenannten \"Guarded Patterns\" (im Beispiel oben \"<code>String s &amp;&amp; s.length() &gt; 5<\/code>\") ver\u00e4ndert. Statt <code>&amp;&amp;<\/code> muss nun das neue Keyword <code>when<\/code> verwendet werden.<\/p>\n\n\n\n<p>Das Beispiel von oben wird in Java 19 wie folgt notiert:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">switch<\/span> (obj) {\n  <span class=\"hljs-keyword\">case<\/span> String s when s.length() &gt; <span class=\"hljs-number\">5<\/span> -&gt; System.out.println(s.toUpperCase());\n  <span class=\"hljs-keyword\">case<\/span> String s                     -&gt; System.out.println(s.toLowerCase());\n\n  <span class=\"hljs-keyword\">case<\/span> Integer i                    -&gt; System.out.println(i * i);\n\n  <span class=\"hljs-keyword\">default<\/span> -&gt; {}\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><code>when<\/code> ist ein sogenanntes \"contextual keyword\" und hat damit nur innerhalb eines <code>case<\/code>-Labels eine Bedeutung. Solltest du in deinem Code Variablen oder Methoden mit dem Namen \"when\" haben, musst du daran nichts \u00e4ndern.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"record-patterns-preview-jep-405\">Record Patterns (Preview) \u2013 JEP 405<\/h3>\n\n\n\n<p>Wir bleiben beim Thema \"Pattern Matching\" und kommen zu den \"Record Patterns\". Wenn das Thema \"Records\" neu f\u00fcr dich ist, empfehle ich dir zun\u00e4chst den Artikel \"<a href=\"\/de\/java\/java-records\/\">Records in Java<\/a>\" zu lesen.<\/p>\n\n\n\n<p>Was ein Record Pattern ist, erkl\u00e4re ich am besten an einem Beispiel. Nehmen wir an, wir haben folgenden Record definiert:<\/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\">Position<\/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-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>Au\u00dferdem haben wir eine <code>print()<\/code>-Methode, die beliebige Objekte, unter anderem auch Positionen, ausgeben kann:<\/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\">private<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">print<\/span><span class=\"hljs-params\">(Object object)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">if<\/span> (object <span class=\"hljs-keyword\">instanceof<\/span> Position position) {\n    System.out.println(<span class=\"hljs-string\">\"object is a position, x = \"<\/span> + position.x() \n                                         + <span class=\"hljs-string\">\", y = \"<\/span> + position.y());\n  }\n  <span class=\"hljs-comment\">\/\/ else ...<\/span>\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>Falls du \u00fcber die verwendete Schreibweise stolperst \u2013 sie wurde in <a href=\"\/de\/java\/java-16-features\/#Pattern_Matching_for_instanceof\">Java 16<\/a> als \"Pattern Matching for instanceof\" eingef\u00fchrt.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Record Pattern mit instanceof<\/h4>\n\n\n\n<p>Ab Java 19 erm\u00f6glicht uns <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/405\" target=\"_blank\">JDK Enhancement Proposal 405<\/a> ein sogenanntes \"Record Pattern\" einzusetzen. Damit k\u00f6nnen wir den Code auch wie folgt schreiben:<\/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\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">print<\/span><span class=\"hljs-params\">(Object object)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-function\">object <span class=\"hljs-keyword\">instanceof<\/span> <span class=\"hljs-title\">Position<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span>) <\/span>{\n    System.out.println(<span class=\"hljs-string\">\"object is a position, x = \"<\/span> + x + <span class=\"hljs-string\">\", y = \"<\/span> + y);\n  } \n  <span class=\"hljs-comment\">\/\/ else ...<\/span>\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>Anstatt auf \"<code>Position position<\/code>\" zu matchen und im nachfolgenden Code auf <code>position<\/code> zuzugreifen, matchen wir nun auf \"<code>Position(int x, int y)<\/code>\" und k\u00f6nnen im folgenden Code direkt auf <code>x<\/code> und <code>y<\/code> zugreifen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Record Pattern mit switch<\/h4>\n\n\n\n<p>Das urspr\u00fcngliche Beispiel k\u00f6nnen wir seit <a href=\"\/de\/java\/java-17-features\/#Pattern_Matching_for_switch_Preview\">Java 17<\/a> auch als <code>switch<\/code>-Statement schreiben:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">print<\/span><span class=\"hljs-params\">(Object object)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">switch<\/span> (object) {\n    <span class=\"hljs-keyword\">case<\/span> Position position\n        -&gt; System.out.println(<span class=\"hljs-string\">\"object is a position, x = \"<\/span> + position.x() \n                                                + <span class=\"hljs-string\">\", y = \"<\/span> + position.y());\n    <span class=\"hljs-comment\">\/\/ other cases ...<\/span>\n  }\n}\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>Auch im switch-Statement k\u00f6nnen wir seit Java 19 ein Record Pattern benutzen:<\/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\">private<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">print<\/span><span class=\"hljs-params\">(Object object)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">switch<\/span> (object) {\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-title\">Position<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> \n        -&gt; System.out.<span class=\"hljs-title\">println<\/span><span class=\"hljs-params\">(<span class=\"hljs-string\">\"object is a position, x = \"<\/span> + x + <span class=\"hljs-string\">\", y = \"<\/span> + y)<\/span><\/span>;\n\n    <span class=\"hljs-comment\">\/\/ other cases ...<\/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<h4 class=\"wp-block-heading\">Verschachtelte Record Patterns<\/h4>\n\n\n\n<p>Es ist auch m\u00f6glich verschachtelte Records zu matchen \u2013 auch das m\u00f6chte ich an einem Beispiel demonstrieren.<\/p>\n\n\n\n<p>Wir definieren zun\u00e4chst einen zweiten Record, <code>Path<\/code>, mit einer Start- und einer Zielposition:<\/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\">Path<\/span><span class=\"hljs-params\">(Position from, Position to)<\/span> <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Unsere <code>print()<\/code>-Methode kann nun mit Hilfe eines Record Patterns ganz einfach alle X- und Y-Koordinaten des Pfades ausgeben:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">print<\/span><span class=\"hljs-params\">(Object object)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">if<\/span> (<span class=\"hljs-function\">object <span class=\"hljs-keyword\">instanceof<\/span> <span class=\"hljs-title\">Path<\/span><span class=\"hljs-params\">(Position(<span class=\"hljs-keyword\">int<\/span> x1, <span class=\"hljs-keyword\">int<\/span> y1)<\/span>, <span class=\"hljs-title\">Position<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x2, <span class=\"hljs-keyword\">int<\/span> y2)<\/span>)) <\/span>{\n    System.out.println(<span class=\"hljs-string\">\"object is a path, x1 = \"<\/span> + x1 + <span class=\"hljs-string\">\", y1 = \"<\/span> + y1 \n                                     + <span class=\"hljs-string\">\", x2 = \"<\/span> + x2 + <span class=\"hljs-string\">\", y2 = \"<\/span> + y2);\n  }\n  <span class=\"hljs-comment\">\/\/ else ...<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Auch das k\u00f6nnen wir alternativ als <code>switch<\/code>-Statement schreiben:<\/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\">private<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">print<\/span><span class=\"hljs-params\">(Object object)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">switch<\/span> (object) {\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-title\">Path<\/span><span class=\"hljs-params\">(Position(<span class=\"hljs-keyword\">int<\/span> x1, <span class=\"hljs-keyword\">int<\/span> y1)<\/span>, <span class=\"hljs-title\">Position<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x2, <span class=\"hljs-keyword\">int<\/span> y2)<\/span>)\n        -&gt; System.out.<span class=\"hljs-title\">println<\/span><span class=\"hljs-params\">(<span class=\"hljs-string\">\"object is a path, x1 = \"<\/span> + x1 + <span class=\"hljs-string\">\", y1 = \"<\/span> + y1 \n                                            + <span class=\"hljs-string\">\", x2 = \"<\/span> + x2 + <span class=\"hljs-string\">\", y2 = \"<\/span> + y2)<\/span><\/span>;\n    <span class=\"hljs-comment\">\/\/ other cases ...<\/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>Record Patterns bieten uns also eine elegante M\u00f6glichkeit nach einer Typpr\u00fcfung auf die Elemente eines Records zuzugreifen.<\/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<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"virtual-threads-preview-jep-425\">Virtual Threads (Preview) \u2013 JEP 425<\/h3>\n\n\n\n<p>Die spannendeste Neuerung in Java 19 sind f\u00fcr mich \"Virtual Threads\". Diese werden seit einigen Jahren in <a rel=\"noopener\" href=\"https:\/\/openjdk.org\/projects\/loom\/\" target=\"_blank\">Project Loom<\/a> entwickelt und konnten bisher nur mit einem selbst compiliertem JDK getestet werden.<\/p>\n\n\n\n<p>Mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/425\" target=\"_blank\">JDK Enhancement Proposal 425<\/a> halten virtuelle Threads endlich Einzug in das offizielle JDK \u2013 und zwar direkt im Preview-Status, so dass keine wesentlichen \u00c4nderungen an der API mehr zu erwarten sind.<\/p>\n\n\n\n<p>Warum wir virtuelle Threads brauchen, was sie sind, wie sie funktionieren und wie man sie einsetzt, erf\u00e4hrst du im <a href=\"\/de\/java\/virtual-threads\/\">Hauptartikel \u00fcber virtuelle Threads<\/a>, den du dir auf keinen Fall entgehen lassen solltest.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"structured-concurrency-incubator-jep-428\">Structured Concurrency (Incubator) \u2013 JEP 428<\/h3>\n\n\n\n<p>Ebenfalls in <a rel=\"noopener\" href=\"https:\/\/openjdk.org\/projects\/loom\/\" target=\"_blank\">Project Loom<\/a> entwickelt und mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org\/jeps\/428\" target=\"_blank\">JDK Enhancement Proposal 428<\/a> in Java 19 zun\u00e4chst als Incubator-Feature ver\u00f6ffentlicht wird die sogenannte \"Structured Concurrency\".<\/p>\n\n\n\n<p>Wenn eine Aufgabe aus mehreren Teilaufgaben besteht, die parallel abgearbeitet werden k\u00f6nnen, erlaubt Structured Concurrency es uns, dies auf eine Art und Weise zu implementieren, die besonders gut les- und wartbar ist.<\/p>\n\n\n\n<p>Wie das genau funktioniert, erf\u00e4hrst du im <a href=\"\/de\/java\/structured-concurrency-structuredtaskscope\/\">Hauptartikel \u00fcber Structured Concurrency<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"foreign-function-memory-api-preview-jep-424\">Foreign Function &amp; Memory API (Preview) \u2013 JEP 424<\/h3>\n\n\n\n<p>Im <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/projects\/panama\/\" target=\"_blank\">Project Panama<\/a> wird seit langem an einem Ersatz f\u00fcr das umst\u00e4ndlich zu benutzende, fehleranf\u00e4llige und langsame Java Native Interface (JNI) gearbeitet.<\/p>\n\n\n\n<p>Bereits in <a href=\"\/de\/java\/java-14-features\/#Foreign-Memory_Access_API_Incubator\">Java 14<\/a> und <a href=\"\/de\/java\/java-16-features\/#Foreign_Linker_API_Incubator_Foreign-Memory_Access_API_Third_Incubator\">Java 16<\/a> wurden die \"Foreign Memory Access API\" und die \"Foreign Linker API\" vorgestellt \u2013 beide zun\u00e4chst einzeln im Incubator-Stadium. In <a href=\"\/de\/java\/java-17-features\/#Foreign_Function_Memory_API_Incubator\">Java 17<\/a> wurden diese APIs zur \"Foreign Function &amp; Memory API\" (FFM API) vereint, die bis <a href=\"\/de\/java\/java-18-features\/#Foreign_Function_Memory_API_Second_Incubator\">Java 18<\/a> im Incubator-Stadium blieb.<\/p>\n\n\n\n<p>In Java 19 ist die neue API mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/424\" target=\"_blank\">JDK Enhancement Proposal 424<\/a> endlich im Preview-Stadium angekommen, d. h. dass nur noch kleine \u00c4nderungen und Bugfixes vorgenommen werden. Damit ist es an der Zeit die neue API hier vorzustellen!<\/p>\n\n\n\n<p>Die Foreign Function &amp; Memory API erm\u00f6glicht den Zugriff auf nativen Speicher (also Speicher au\u00dferhalb des Java Heaps) sowie den Zugriff auf nativen Code (z. B. auf C-Libraries) direkt aus Java heraus.<\/p>\n\n\n\n<p>Wie das funktioniert, zeige ich an einem Beispiel. Zu tief werde ich hier allerdings nicht in die Thematik einsteigen, da die meisten Java-Entwickler selten bis nie auf nativen Speicher und Code zugreifen m\u00fcssen.<\/p>\n\n\n\n<p>Hier ist ein einfaches Beispiel, das einen String im Off-Heap-Memory speichert und darauf die \"strlen\"-Funktion der C-Standard-Bibliothek aufruft:<\/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 shcb-code-table shcb-line-numbers\"><span class='shcb-loc'><span><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">FFMTest<\/span> <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">(String&#091;] args)<\/span> <span class=\"hljs-keyword\">throws<\/span> Throwable <\/span>{\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ 1. Get a lookup object for commonly used libraries<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    SymbolLookup stdlib = Linker.nativeLinker().defaultLookup();\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ 2. Get a handle to the \"strlen\" function in the C standard library<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    MethodHandle strlen = Linker.nativeLinker().downcallHandle(\n<\/span><\/span><span class='shcb-loc'><span>        stdlib.lookup(<span class=\"hljs-string\">\"strlen\"<\/span>).orElseThrow(), \n<\/span><\/span><span class='shcb-loc'><span>        FunctionDescriptor.of(JAVA_LONG, ADDRESS));\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ 3. Convert Java String to C string and store it in off-heap memory<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    MemorySegment str = implicitAllocator().allocateUtf8String(<span class=\"hljs-string\">\"Happy Coding!\"<\/span>);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-comment\">\/\/ 4. Invoke the foreign function<\/span>\n<\/span><\/span><span class='shcb-loc'><span>    <span class=\"hljs-keyword\">long<\/span> len = (<span class=\"hljs-keyword\">long<\/span>) strlen.invoke(str);\n<\/span><\/span><span class='shcb-loc'><span>\n<\/span><\/span><span class='shcb-loc'><span>    System.out.println(<span class=\"hljs-string\">\"len = \"<\/span> + len);\n<\/span><\/span><span class='shcb-loc'><span>  }\n<\/span><\/span><span class='shcb-loc'><span>}\n<\/span><\/span><\/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>Interessant ist der <code>FunctionDescriptor<\/code> in Zeile 9: dieser definiert als ersten Parameter den R\u00fcckgabetyp der Funktion und als weitere Parameter die Argumente der Funktion. Der <code>FunctionDescriptor<\/code> sorgt daf\u00fcr, dass alle Java-Typen ordnungsgem\u00e4\u00df in C-Typen umgewandelt werden und umgekehrt. <\/p>\n\n\n\n<p>Da die FFM API sich noch im Preview-Stadium befindet, m\u00fcssen zum Compilieren und Starten ein paar zus\u00e4tzliche Parameter angegeben werden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ javac --enable-preview --source 19 FFMTest.java\n$ java --enable-preview FFMTest<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><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>Wer schon einmal mit JNI gearbeitet hat \u2013 und sich erinnert, wie viel Java- und C-Boilerplate-Code man schreiben und synchron halten musste \u2013 wird erkennen, dass sich der Aufwand f\u00fcr den Aufruf der nativen Funktion um Gr\u00f6\u00dfenordnungen reduziert hat.<\/p>\n\n\n\n<p>Wer sich tiefer mit der Materie besch\u00e4ftigen m\u00f6chte: im <a href=\"https:\/\/openjdk.org:443\/jeps\/424\" target=\"_blank\" rel=\"noopener\">JEP<\/a> findest du weitere, komplexere Beispiele. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vector-api-fourth-incubator-jep-426\">Vector API (Fourth Incubator) \u2013 JEP 426<\/h3>\n\n\n\n<p>Die neue Vector-API hat nichts mit der <code>java.util.Vector<\/code>-Klasse zu tun. Tats\u00e4chlich geht es um eine neue API f\u00fcr mathematische Vektorrechnung und deren Abbildung auf moderne SIMD (Single-Instruction-Multiple-Data)-CPUs.<\/p>\n\n\n\n<p>Die Vector-API ist seit <a href=\"\/de\/java\/java-16-features\/#Vector_API_Incubator\">Java 16<\/a> als Incubator Teil des JDK und wurde in <a href=\"\/de\/java\/java-17-features\/#Vector_API_Second_Incubator\">Java 17<\/a> und <a href=\"\/de\/java\/java-18-features\/#Vector_API_Third_Incubator\">Java 18<\/a> weiterentwickelt.<\/p>\n\n\n\n<p>Mit <a href=\"https:\/\/openjdk.org:443\/jeps\/426\">JDK Enhancement Proposal 426<\/a> liefert Java 19 die vierte Iteration, in der die API um neue Vektoroperationen erweitert wurde \u2013 sowie um die M\u00f6glichkeit Vektoren in Memory-Segmenten (ein Feature der <a href=\"#Foreign_Function_Memory_API_Preview_-_JEP_424\">Foreign Function &amp; Memory API<\/a>) zu speichern und sie daraus zu lesen.<\/p>\n\n\n\n<p>Incubator-Features k\u00f6nnen noch wesentlichen \u00c4nderungen unterliegen, ich werde die API daher hier nicht im Detail vorstellen. Das werde ich nachholen, sobald die Vector-API in den Preview-Status \u00fcbergegangen ist.<\/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 19 wurden einige Funktionen als \"deprecated\" markiert bzw. au\u00dfer Betrieb gesetzt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"deprecation-of-locale-class-constructors\">Deprecation of Locale class constructors<\/h3>\n\n\n\n<p>In Java 19 wurden die \u00f6ffentlichen Konstruktoren der <code>Locale<\/code>-Klasse als \"deprecated\" markiert.<\/p>\n\n\n\n<p>Stattdessen sollten wir die neue statische Factory-Methode <code>Locale.of()<\/code> verwenden. Dadurch wird sichergestellt, dass es pro <code>Locale<\/code>-Konfiguration nur eine Instanz gibt.<\/p>\n\n\n\n<p>Das folgende Beispiel zeigt die Nutzung der Factory-Methode im Vergleich zum Konstruktor:<\/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\">Locale german1 = <span class=\"hljs-keyword\">new<\/span> Locale(<span class=\"hljs-string\">\"de\"<\/span>); <span class=\"hljs-comment\">\/\/ deprecated<\/span>\nLocale germany1 = <span class=\"hljs-keyword\">new<\/span> Locale(<span class=\"hljs-string\">\"de\"<\/span>, <span class=\"hljs-string\">\"DE\"<\/span>); <span class=\"hljs-comment\">\/\/ deprecated<\/span>\n\nLocale german2 = Locale.of(<span class=\"hljs-string\">\"de\"<\/span>);\nLocale germany2 = Locale.of(<span class=\"hljs-string\">\"de\"<\/span>, <span class=\"hljs-string\">\"DE\"<\/span>);\n\nSystem.out.println(<span class=\"hljs-string\">\"german1  == Locale.GERMAN  = \"<\/span> + (german1 == Locale.GERMAN));\nSystem.out.println(<span class=\"hljs-string\">\"germany1 == Locale.GERMANY = \"<\/span> + (germany1 == Locale.GERMANY));\nSystem.out.println(<span class=\"hljs-string\">\"german2  == Locale.GERMAN  = \"<\/span> + (german2 == Locale.GERMAN));\nSystem.out.println(<span class=\"hljs-string\">\"germany2 == Locale.GERMANY = \"<\/span> + (germany2 == Locale.GERMANY));\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 du diesen Code startest, wirst du sehen, dass die \u00fcber die Factory-Methode gelieferten Objekte identisch sind mit den <code>Locale<\/code>-Konstanten \u2013 die per Konstruktur erzeugten logischerweise nicht.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"java-lang-threadgroup-is-degraded\">java.lang.ThreadGroup is degraded<\/h3>\n\n\n\n<p>In <a href=\"\/de\/java\/java-14-features\/#Thread_SuspendResume_Are_Deprecated_for_Removal\">Java 14<\/a> und <a href=\"\/de\/java\/java-16-features\/#Terminally_Deprecated_ThreadGroup_stop_destroy_isDestroyed_setDaemon_and_isDaemon\">Java 16<\/a> wurden mehrere <code>Thread<\/code>- und <code>ThreadGroup<\/code>-Methoden als \"deprecated for removal\" markiert. Die Gr\u00fcnde daf\u00fcr erf\u00e4hrst du in den verlinkten Abschnitten.<\/p>\n\n\n\n<p>Die folgenden dieser Methoden wurden in Java 19 au\u00dfer Betrieb gesetzt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>ThreadGroup.destroy()<\/code> \u2013 der Aufruf dieser Methode wird ignoriert.<\/li>\n\n\n\n<li><code>ThreadGroup.isDestroyed()<\/code> \u2013 gibt immer <code>false<\/code> zur\u00fcck.<\/li>\n\n\n\n<li><code>ThreadGroup.setDaemon()<\/code> \u2013 setzt das <code>daemon<\/code>-Flag, dies hat allerdings keine Wirkung mehr.<\/li>\n\n\n\n<li><code>ThreadGroup.getDaemon()<\/code> \u2013 gibt den Wert des ungenutzten <code>daemon<\/code>-Flags zur\u00fcck.<\/li>\n\n\n\n<li><code>ThreadGroup.suspend()<\/code>, <code>resume()<\/code> und <code>stop()<\/code> werfen eine <code>UnsupportedOperationException<\/code>.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sonstige-aenderungen-in-java-19\">Sonstige \u00c4nderungen in Java 19<\/h2>\n\n\n\n<p>In diesem Abschnitt findest du \u00c4nderungen\/Erweiterungen, die nicht f\u00fcr alle Java-Entwickler relevant sein d\u00fcrften.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"automatic-generation-of-the-cds-archive\">Automatic Generation of the CDS Archive<\/h3>\n\n\n\n<p>Application Class Data Sharing (kurz: \u201eApplication CDS\u201d oder \u201eAppCDS\u201d) wurde <a href=\"\/de\/java\/java-10-features\/#Application_Class-Data_Sharing_Schritt_fuer_Schritt\">in Java 10 eingef\u00fchrt<\/a>, die Konfiguration wurde <a href=\"\/de\/java\/java-13-features\/#Dynamic_CDS_Archives\">in Java 13 deutlich vereinfacht<\/a>. <\/p>\n\n\n\n<p>Application CDS erm\u00f6glicht es, beim Betrieb mehrerer JVMs auf einer Maschine, die Klassen einer Anwendung einmalig in den Speicher zu laden und diesen Speicherbereich mit allen JVMs zu teilen. Dadurch wird Speicher gespart sowie Zeit f\u00fcr das Laden der <em>.jar<\/em>- und <em>.class<\/em>-Dateien und deren Umwandeln in ein Platform-spezifisches Bin\u00e4rformat.<\/p>\n\n\n\n<p>Mit Java 19 wurde die Konfiguration von AppCDS noch einmal vereinfacht. Mit folgendem Parameter kann nun automatisch ein CDS-Archiv erzeugt oder aktualisiert werden.<\/p>\n\n\n\n<p>Die Anwendung aus den Beispielen der oben verlinkten Artikel zu Java 10 und 13 kann nun wie folgt gestartet werden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">java -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=helloworld.jsa \\\n    -cp target\/helloworld.jar eu.happycoders.appcds.Main<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><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>Das Shared Archive wird nun erzeugt, wenn es nicht existiert oder wenn es von einer \u00e4lteren Java-Version erzeugt wurde.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"linux-risc-v-port-jep-422\">Linux\/RISC-V Port \u2013 JEP 422<\/h3>\n\n\n\n<p>Aufgrund zunehmender Verbreitung von RISC-V-Hardware, wurde mit <a href=\"https:\/\/openjdk.org:443\/jeps\/422\" target=\"_blank\" rel=\"noopener\">JEP 422<\/a> ein Port f\u00fcr die entsprechende Architektur zur Verf\u00fcgung gestellt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"additional-date-time-formats\">Additional Date-Time Formats<\/h3>\n\n\n\n<p>\u00dcber die Methoden <code>DateTimeFormatter.ofLocalizedDate(...)<\/code>, <code>ofLocalizedTime(...)<\/code> und <code>ofLocalizedDateTime(...)<\/code> und dem nachfolgenden Aufruf von <code>withLocale(...)<\/code> k\u00f6nnen wir uns einen Datum-\/Zeit-Formatter erzeugen lassen. Das genaue Format steuern wir dabei \u00fcber das Enum <code>FormatStyle<\/code>, das die Werte <code>FULL<\/code>, <code>LONG<\/code>, <code>MEDIUM<\/code> und <code>SHORT<\/code> annehmen kann.<\/p>\n\n\n\n<p>In Java 19 kam die Methode <code>ofLocalizedPattern(String requestedTemplate)<\/code> hinzu, mit der wir auch flexible Formate definieren k\u00f6nnen. Hier ein Beispiel:<\/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\">LocalDate now = LocalDate.now();\nDateTimeFormatter formatter = DateTimeFormatter.ofLocalizedPattern(<span class=\"hljs-string\">\"yMMM\"<\/span>);\nSystem.out.println(<span class=\"hljs-string\">\"US:      \"<\/span> + formatter.withLocale(Locale.US).format(now));\nSystem.out.println(<span class=\"hljs-string\">\"Germany: \"<\/span> + formatter.withLocale(Locale.GERMANY).format(now));\nSystem.out.println(<span class=\"hljs-string\">\"Japan:   \"<\/span> + formatter.withLocale(Locale.JAPAN).format(now));<\/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>Der Code gibt folgendes aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">US:      Jan 2024\nGermany: Jan. 2024\nJapan:   2024\u5e741\u6708\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><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>F\u00fcr diese \u00c4nderung gibt es kein JDK Enhancement Proposal. Du findest sie in den <a href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/19all-relnotes.html#JDK-8176706\" target=\"_blank\" rel=\"noopener\">JDK 19 Release Notes<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"new-system-properties-for-system-out-and-system-err\">New System Properties for System.out and System.err<\/h3>\n\n\n\n<p>Seit Version 18 verwendet Java bei der Ausgabe nach <code>System.out<\/code> und <code>System.err<\/code> automatisch die Zeichenkodierung der Konsole bzw. des Terminals. Unter Linux ist das in der Regel UTF-8 und unter Windows die Code Page 437.<\/p>\n\n\n\n<p>Speichere einmal folgendes Programm in der Datei <em>Test.java<\/em>:<\/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-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Test<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">(String&#091;] args)<\/span> <\/span>{\n    System.out.println(<span class=\"hljs-string\">\"\u00c1 \u00e9 \u00f6 \u00df \u20ac \u00bc\"<\/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>Wenn du dieses unter Linux startest, werden wahrscheinlich alle Zeichen korrekt angezeigt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ java Test.java\n\u00c1 \u00e9 \u00f6 \u00df \u20ac \u00bc<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><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>Wenn du das Programm hingegen unter Windows ausf\u00fchrst, siehst du h\u00f6chstwahrscheinlich folgende Ausgabe (ein Fragezeichen statt dem \u00c1 und dem \u20ac):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">C:\\...&gt;java Test.java\n? \u00e9 \u00f6 \u00df ? \u00bc<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><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>Das liegt daran, dass unter Windows standardm\u00e4\u00dfig die Code Page 437 aktiviert ist, die die entsprechenden Zeichen nicht enth\u00e4lt.<\/p>\n\n\n\n<p>Du kannst die Windows-Konsole wie folgt auf UTF-8 umschalten:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">C:\\...&gt;chcp 65001\nActive code page: 65001<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><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>Wenn du das Programm erneut startest, siehst du nun alle Zeichen korrekt.<\/p>\n\n\n\n<p>Falls die automatische Erkennung des verwendeten Zeichensatzes nicht funktionieren sollte, kannst du ihn ab Java 19 \u00fcber folgende VM-Optionen z. B. auf UTF-8 einstellen:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>-Dstdout.encoding=utf-8 -Dstderr.encoding=utf-8<\/code><\/p>\n\n\n\n<p>Wenn du das nicht bei jedem Programmstart machen m\u00f6chtest, kannst du diese Einstellungen auch global festlegen, indem du die folgende Umgebungsvariable definierst (ja, diese beginnt mit einem Unterstrich):<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>_JAVA_OPTIONS=\"-Dstdout.encoding=utf-8 -Dstderr.encoding=utf-8\"<\/code><\/p>\n\n\n\n<p>F\u00fcr diese \u00c4nderung gibt es kein JDK Enhancement Proposal. Du findest sie in den <a href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/19all-relnotes.html#JDK-8283620\" target=\"_blank\" rel=\"noopener\">JDK 19 Release Notes<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vollstaendige-liste-aller-aenderungen-in-java-19\">Vollst\u00e4ndige Liste aller \u00c4nderungen in Java 19<\/h3>\n\n\n\n<p>Neben den in diesem Artikel pr\u00e4sentierten JDK Enhancement Proposals (JEPs) und \u00c4nderungen an den Klassenbibliotheken gibt es zahlreiche kleinere \u00c4nderungen, die den Rahmen dieses Artikels sprengen w\u00fcrden. Eine vollst\u00e4ndige Liste findest du in den <a href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/19all-relnotes.html\" target=\"_blank\" rel=\"noopener\">JDK 19 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>In Java 19 haben die lang ersehnten, in Project Loom entwickelten, <a href=\"\/de\/java\/virtual-threads\/\">virtuellen Threads<\/a> endlich ihren Weg ins JDK gefunden (wenn auch zun\u00e4chst im Preview-Stadium). Ich hoffe du bist ebenso begeistert wie ich und kannst es nicht abwarten virtuelle Threads in deinen Projekten einzusetzen!<\/p>\n\n\n\n<p>Strukturierte Concurrency (noch im Incubator-Stadium) wird darauf aufbauend die Verwaltung von Tasks, die in parallele Subtasks aufgeteilt werden, deutlich vereinfachen.<\/p>\n\n\n\n<p>Die in den letzten JDK-Versionen nach und nach weiterentwickelten Pattern-Matching-M\u00f6glichkeiten in <code>instanceof<\/code> und <code>switch<\/code> wurden um Record Patterns erweitert. <\/p>\n\n\n\n<p>Die Preview- und Incubator Features \"Pattern Matching for switch\", \"Foreign Function &amp; Memory API\" und \"Vector API\" wurden in die jeweils n\u00e4chste Preview- bzw. Incubator-Runde geschickt.<\/p>\n\n\n\n<p>Die Ausgabe auf die Konsole erfolgt standardm\u00e4\u00dfig im Standard-Encoding des Betriebssystems und muss ggf. per VM-Option umgestellt werden.<\/p>\n\n\n\n<p>HashMaps bieten neue Factory-Methoden an, um Maps mit ausreichender Kapazit\u00e4t f\u00fcr eine vorgegebene Anzahl Mappings zu erstellen.<\/p>\n\n\n\n<p>Diverse sonstige \u00c4nderungen runden wie immer das Release ab. Du kannst Java 19 <a rel=\"noopener\" href=\"https:\/\/jdk.java.net\/19\/\" target=\"_blank\">hier<\/a> herunterladen.<\/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 19 Features mit Beispielen: Virtual Threads (Preview), Record Patterns (Preview), Foreign Function &#038; Memory API (Preview) + mehr<\/p>\n","protected":false},"author":1,"featured_media":34253,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_titles_title":"","_seopress_titles_desc":"Die neuen Java 19 Features mit Beispielen: Virtual Threads (Preview), Record Patterns (Preview), Foreign Function & Memory API (Preview) + mehr","_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 19,java 19 features","_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":20639,"_post_count":0,"footnotes":""},"categories":[64],"tags":[176],"class_list":["post-31297","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\/2022\/09\/java-19-features.jpg",1770,986,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features.jpg",150,84,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features.jpg",768,428,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features.jpg",1024,570,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-224x125.jpg",224,125,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-504x281.jpg",504,281,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-672x374.jpg",672,374,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-400x223.jpg",400,223,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-600x334.jpg",600,334,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-800x446.jpg",800,446,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-944x526.jpg",944,526,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-1200x668.jpg",1200,668,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features-1770x735.jpg",1770,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features.jpg",1536,856,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2022\/09\/java-19-features.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 19 Features mit Beispielen: Virtual Threads (Preview), Record Patterns (Preview), Foreign Function & Memory API (Preview) + mehr","public_identification_id":"24b17bd15d0e4658a6aaeaa24424c271","private_identification_id":"adc56073e6ae49ecaeffb88025e93844","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/31297","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=31297"}],"version-history":[{"count":10,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/31297\/revisions"}],"predecessor-version":[{"id":52400,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/31297\/revisions\/52400"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/34253"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=31297"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=31297"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=31297"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}