{"id":23022,"date":"2021-10-20T09:10:15","date_gmt":"2021-10-20T07:10:15","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=23022"},"modified":"2024-11-27T14:59:52","modified_gmt":"2024-11-27T13:59:52","slug":"java-10-features","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/java-10-features\/","title":{"rendered":"Java 10 Features (mit Beispielen)"},"content":{"rendered":"\n<p>Mit Java 10 begann am 20. M\u00e4rz 2018 der sechsmonatige Release-Zyklus des JDKs. Statt jahrelang auf ein gro\u00dfes Update warten zu m\u00fcssen, werden wir nun halbj\u00e4hrlich mit neuen Features \u2013 und Previews neuer Features \u2013 verw\u00f6hnt.<\/p>\n\n\n\n<p>Ich habe die \u00c4nderungen nach Relevanz f\u00fcr die t\u00e4gliche Entwicklerarbeit sortiert. \u00c4nderungen an der Sprache selbst stehen ganz oben, gefolgt von Erweiterungen an der JDK-Klassenbibliothek.<\/p>\n\n\n\n<p>Danach folgen Performance-Verbesserungen, Deprecations und L\u00f6schungen und zuletzt sonstige \u00c4nderungen, von denen wir Entwickler wenig mitbekommen (sofern wir nicht am JDK selbst mitarbeiten).<\/p>\n\n\n\n<p>Als Kapitel-\u00dcberschriften verwende ich die englischen Bezeichnungen der JDK Enhancement Proposals (JEPs). Diese auf deutsch zu \u00fcbersetzen w\u00fcrde eher verwirren.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"local-variable-type-inference-var\">Local-Variable Type Inference (\"var\")<\/h2>\n\n\n\n<p>Seit Java 10 k\u00f6nnen wir zur Deklaration lokaler Variablen (lokal hei\u00dft: innerhalb von Methoden) das Schl\u00fcsselwort <code>var<\/code> verwenden. Das erm\u00f6glicht z. B. folgende Definitionen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"GLSL\" data-shcb-language-slug=\"glsl\"><span><code class=\"hljs language-glsl\">var i = <span class=\"hljs-number\">10<\/span>;\nvar hello = \"Hello world!\";\nvar list = List.of(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">2<\/span>, <span class=\"hljs-number\">3<\/span>, <span class=\"hljs-number\">4<\/span>, <span class=\"hljs-number\">5<\/span>);\nvar httpClient = HttpClient.newBuilder().build();\nvar status = getStatus();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">GLSL<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">glsl<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Zum Vergleich \u2013 so sehen die Definitionen in klassischer Schreibweise aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">int<\/span> i = <span class=\"hljs-number\">10<\/span>;\nString hello = <span class=\"hljs-string\">\"Hello world!\"<\/span>;\nList&lt;Integer&gt; list = List.of(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">2<\/span>, <span class=\"hljs-number\">3<\/span>, <span class=\"hljs-number\">4<\/span>, <span class=\"hljs-number\">5<\/span>);\nHttpClient httpClient = HttpClient.newBuilder().build();\nStatus status = getStatus();<\/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>Inwieweit man <code>var<\/code> verwendet, wird vermutlich in vielen Teams zu langen Diskussionen f\u00fchren. Ich setze es dann ein, wenn es a) deutlich k\u00fcrzer ist und ich b) den Datentyp klar im Code erkennen kann.<\/p>\n\n\n\n<p>Im Beispiel oben w\u00e4re das in Zeile 3 und 4 der Fall (bei <code>List<\/code> und <code>HttpClient<\/code>). Die klassiche Schreibweise ist in beiden F\u00e4llen deutlich l\u00e4nger. Und die Zuweisungen auf der rechten Seite \u2013 also <code>List.of()<\/code> und <code>HttpClient.newBuilder().build()<\/code> \u2013 lassen mich den Datentyp klar erkennen.<\/p>\n\n\n\n<p>In folgenden F\u00e4llen w\u00fcrde ich hingegen auf <code>var<\/code> verzichten:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>In Zeile 1 spart man kein einziges Zeichen; hier w\u00fcrde ich bei <code>int<\/code> bleiben.<\/li>\n\n\n\n<li>In Zeile 2 ist <code>var<\/code> nur minimal k\u00fcrzer als <code>String<\/code> \u2013 von daher w\u00fcrde ich auch hier eher <code>String<\/code> verwenden. Ich verstehe aber auch, wenn Teams sich hier anders entscheiden.<\/li>\n\n\n\n<li>In Zeile 5 w\u00fcrde ich ganz klar bei der alten Schreibweise bleiben. Ansonsten kann ich nicht auf Anhieb erkennen, was <code>getStatus()<\/code> zur\u00fcckliefert. Ist es ein <code>int<\/code>? Ein <code>String<\/code>? Ein Enum? Ein komplexes Value Object? Oder gar eine JPA-Entity aus der Datenbank?<\/li>\n<\/ul>\n\n\n\n<p>Eine ausf\u00fchrlichere Abhandlung dar\u00fcber, wann man <code>var<\/code> einsetzen sollte und wann nicht, findest Du in den offiziellen <a rel=\"noopener\" href=\"https:\/\/openjdk.org\/projects\/amber\/guides\/lvti-style-guide\" target=\"_blank\">Style Guidelines<\/a>. Wichtig ist, dass ihr euch im Team auf eine konsistente Verwendung einigt.<\/p>\n\n\n\n<p><em>(Local-Variable Type Inference ist definiert im <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/286\" target=\"_blank\">JDK Enhancement Proposal 286<\/a>.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"immutable-collections\">Immutable Collections<\/h2>\n\n\n\n<p>Das Java Collections Framework bietet mit den Methoden <code>Collections.unmodifiableList()<\/code>, <code>unmodifiableSet()<\/code>,  <code>unmodifiableMap()<\/code>, <code>unmodifiableCollection()<\/code> \u2013 und vier weiteren Varianten f\u00fcr sortierte und navigierbare Sets und Maps \u2013 die M\u00f6glichkeit unver\u00e4nderbare Wrapper f\u00fcr Collection-Klassen zu erzeugen.<\/p>\n\n\n\n<p>Hier ein Beispiel:<\/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\">List&lt;Integer&gt; list = <span class=\"hljs-keyword\">new<\/span> ArrayList&lt;&gt;();\nlist.add(<span class=\"hljs-number\">1<\/span>);\nlist.add(<span class=\"hljs-number\">2<\/span>);\nlist.add(<span class=\"hljs-number\">3<\/span>);\nList&lt;Integer&gt; unmodifiable = Collections.unmodifiableList(list);<\/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>Versuchen wir nun \u00fcber den Wrapper ein Element hinzuzuf\u00fcgen, erhalten wir eine <code>UnsupportedOperationException<\/code>:<\/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\">unmodifiable.add(<span class=\"hljs-number\">4<\/span>);\n\n\u27f6\n\nException in thread <span class=\"hljs-string\">\"main\"<\/span> java.lang.UnsupportedOperationException\n\tat java.base\/java.util.Collections$UnmodifiableCollection.add(...)\n\tat ...<\/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>Der Wrapper h\u00e4lt uns allerdings nicht davon ab, die zugrunde liegende Liste zu modifizeren. Alle nachtr\u00e4glichen \u00c4nderungen an dieser sind auch im Wrapper sichtbar. Denn der Wrapper enth\u00e4lt keine Kopie der Liste, sondern eine View:<\/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\">list.add(<span class=\"hljs-number\">4<\/span>);\nSystem.out.println(<span class=\"hljs-string\">\"unmodifiable = \"<\/span> + unmodifiable);\n\n\u27f6\n\nunmodifiable = &#091;<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">2<\/span>, <span class=\"hljs-number\">3<\/span>, <span class=\"hljs-number\">4<\/span>]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"list-copyof-set-copyof-und-map-copyof\">List.copyOf(), Set.copyOf() und Map.copyOf() <\/h3>\n\n\n\n<p>Mit Java 10 haben wir nun auch die M\u00f6glichkeit, unver\u00e4nderbare Kopien von Collections zu erzeugen. Daf\u00fcr stehen uns die statischen Interface-Methoden <code>List.copyOf()<\/code>, <code>Set.copyOf()<\/code> und <code>Map.copyOf()<\/code> zur Verf\u00fcgung.<\/p>\n\n\n\n<p>Erstellen wir so eine Kopie und modifizieren dann die urspr\u00fcngliche Collection, haben die \u00c4nderungen keine Auswirkungen mehr auf die Kopie:<\/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\">List&lt;Integer&gt; immutable = List.copyOf(list);\nlist.add(<span class=\"hljs-number\">4<\/span>);\nSystem.out.println(<span class=\"hljs-string\">\"immutable = \"<\/span> + immutable);\n\n\u27f6\n\nimmutable = &#091;<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">2<\/span>, <span class=\"hljs-number\">3<\/span>]<\/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>Der Versuch die Kopie zu \u00e4ndern, wird \u2013 genau wie beim Einsatz von <code>unmodifiableList()<\/code> \u2013 mit einer <code>UnsupportedOperationException<\/code> quittiert:<\/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\">immutable.add(<span class=\"hljs-number\">4<\/span>);\n\n\u27f6\n\nException in thread <span class=\"hljs-string\">\"main\"<\/span> java.lang.UnsupportedOperationException\n    at java.base\/java.util.ImmutableCollections.uoe(...)\n    at java.base\/java.util.ImmutableCollections$AbstractImmutableCollection.add(...)\n    at ...<\/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>Hinweis: Solltest du eine \u00e4nderbare Kopie der Liste ben\u00f6tigen, kannst du das seit jeher mit dem Copy Constructor machen:<\/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\">List&lt;Integer&gt; copy = <span class=\"hljs-keyword\">new<\/span> ArrayList&lt;&gt;(list);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"collectors-tounmodifiablelist-tounmodifiableset-und-tounmodifiablemap\">Collectors.toUnmodifiableList(), toUnmodifiableSet() und toUnmodifiableMap()<\/h3>\n\n\n\n<p>Die mittels <code>Collectors.toList()<\/code>, <code>toSet()<\/code> und <code>toMap()<\/code> erstellten Collectoren sammeln die Elemente eines Streams in ver\u00e4nderlichen Listen, Sets und Maps. Das folgende Beispiel zeigt den Einsatz dieser Collectoren und die nachtr\u00e4gliche \u00c4nderung der Ergebnisse:<\/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\">List&lt;Integer&gt; list = IntStream.rangeClosed(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">3<\/span>).boxed().collect(Collectors.toList());\nSet&lt;Integer&gt; set = IntStream.rangeClosed(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">3<\/span>).boxed().collect(Collectors.toSet());\nMap&lt;Integer, String&gt; map = IntStream.rangeClosed(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">3<\/span>).boxed()\n        .collect(Collectors.toMap(Function.identity(), String::valueOf));\n\nlist.add(<span class=\"hljs-number\">4<\/span>);\nset.add(<span class=\"hljs-number\">4<\/span>);\nmap.put(<span class=\"hljs-number\">4<\/span>, <span class=\"hljs-string\">\"4\"<\/span>);\n\nSystem.out.println(<span class=\"hljs-string\">\"list = \"<\/span> + list);\nSystem.out.println(<span class=\"hljs-string\">\"set  = \"<\/span> + set);\nSystem.out.println(<span class=\"hljs-string\">\"map  = \"<\/span> + map);<\/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>Wie zu erwarten, liefert das Programm die folgende Ausgabe (wobei die Elemente des Sets und der Map auch in anderer Reihenfolge auftreten d\u00fcrfen):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">list = &#091;1, 2, 3, 4]\nset  = &#091;1, 2, 3, 4]\nmap  = {1=1, 2=2, 3=3, 4=4}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In Java 10 sind die Methoden <code>Collectors.toUnmodifiableList()<\/code>, <code>toUnmodifiableSet()<\/code> und <code>toUnmodifiableMap()<\/code> hinzugekommen, mit denen wir Stream-Elemente nun auch in unver\u00e4nderlichen Listen, Sets und Maps sammeln k\u00f6nnen:<\/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\">List&lt;Integer&gt; list =\n    IntStream.rangeClosed(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">3<\/span>).boxed().collect(Collectors.toUnmodifiableList());\n\nSet&lt;Integer&gt; set =\n    IntStream.rangeClosed(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">3<\/span>).boxed().collect(Collectors.toUnmodifiableSet());\n\nMap&lt;Integer, String&gt; map = \n    IntStream.rangeClosed(<span class=\"hljs-number\">1<\/span>, <span class=\"hljs-number\">3<\/span>)\n        .boxed()\n        .collect(Collectors.toUnmodifiableMap(Function.identity(), String::valueOf));<\/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>Der Versuch solch eine Liste, Set oder Map zu ver\u00e4ndern, wird mit einer <code>UnsupportedOperationException<\/code> quittiert.<\/p>\n\n\n\n<p><em>(F\u00fcr die Erweiterungen an List, Set, Map und Collectors gibt es kein JDK Enhancement Proposal.)<\/em><\/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=\"optional-orelsethrow\">Optional.orElseThrow()<\/h2>\n\n\n\n<p>Das in Java 8 eingef\u00fchrte <code>Optional<\/code> bietet mit der Methode <code>get()<\/code> die M\u00f6glichkeit, den durch das <code>Optional<\/code> gewrappten Wert auszulesen. Vor dem Aufruf von <code>get()<\/code> sollte immer mit <code>isPresent()<\/code> gepr\u00fcft werden, ob ein Wert existiert:<\/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\">Optional&lt;String&gt; result = getResult();\n<span class=\"hljs-keyword\">if<\/span> (result.isPresent()) {\n  System.out.println(result.get());\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ist das <code>Optional<\/code> leer, w\u00fcrde <code>get()<\/code> sonst eine <code>NoSuchElementException<\/code> werfen.<\/p>\n\n\n\n<p>Um das Risiko einer unbeabsichtigten Exception zu minimieren, geben IDEs und Statische Code-Analyse-Tools eine Warnung aus, wenn <code>get()<\/code> ohne <code>isPresent()<\/code> verwendet wird:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_400\"><img decoding=\"async\" width=\"400\" height=\"61\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Optional-get-warning-v2-400x61.png\" alt=\"IntelliJ-Warnung bei Optional.get() ohne isPresent()\" class=\"wp-image-23227\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Optional-get-warning-v2-400x61.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Optional-get-warning-v2-224x34.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Optional-get-warning-v2-336x51.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Optional-get-warning-v2-504x77.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Optional-get-warning-v2-672x102.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Optional-get-warning-v2-600x92.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Optional-get-warning-v2.png 800w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><figcaption class=\"wp-element-caption\">IntelliJ-Warnung bei Optional.get() ohne isPresent()<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Es gibt allerdings auch F\u00e4lle, in denen eine solche Exception gew\u00fcnscht ist. Bisher musste man den Code mit entsprechenden <code>@SuppressWarnings<\/code>-Annotationen versehen, um die Warnungen zu unterdr\u00fccken.<\/p>\n\n\n\n<p>Java 10 bietet mit der Methode <code>orElseThrow()<\/code> eine sch\u00f6nere L\u00f6sung: Die Methode ist eine exakte Kopie der <code>get()<\/code>-Methode \u2013 nur der Name ist anders. Da aus dem Namen klar ersichtlich ist, dass diese Methode eine Exception werfen kann, sind Missverst\u00e4ndnisse ausgeschlossen. Die statische Code-Analyse moniert die Verwendung nicht mehr als Code Smell.<\/p>\n\n\n\n<p>Hier zum Vergleich der Quellcode beider Methoden:<\/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> T <span class=\"hljs-title\">get<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  <span class=\"hljs-keyword\">if<\/span> (value == <span class=\"hljs-keyword\">null<\/span>) {\n    <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> NoSuchElementException(<span class=\"hljs-string\">\"No value present\"<\/span>);\n  }\n  <span class=\"hljs-keyword\">return<\/span> value;\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> T <span class=\"hljs-title\">orElseThrow<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  <span class=\"hljs-keyword\">if<\/span> (value == <span class=\"hljs-keyword\">null<\/span>) {\n    <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> NoSuchElementException(<span class=\"hljs-string\">\"No value present\"<\/span>);\n  }\n  <span class=\"hljs-keyword\">return<\/span> value;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><em>(F\u00fcr diese Erweiterung gibt es kein JDK Enhancement Proposal.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"time-based-release-versioning\">Time-Based Release Versioning<\/h2>\n\n\n\n<p>Nachdem von Java 8 auf 9 das Versionsformat (endlich) von dem eher kryptischen 1.8.0_291 auf ein deutlich besser lesbares 9.0.4 umgestellt wurde, wurde in Java 10 mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/322\" target=\"_blank\">JEP 322<\/a> noch das Release-Datum hinzugef\u00fcgt \u2013 und f\u00fcr Java 11 bereits im Voraus ein \"LTS\" (Long-Term Support) festgelegt.<\/p>\n\n\n\n<p>Das Kommando <code>java -version<\/code> liefert in Java 8 bis 11 die folgenden Antworten:<\/p>\n\n\n\n<p>Java 8:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ java -version\njava version \"1.8.0_291\"<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Java 9:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ java -version\njava version \"9.0.4\"<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><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>Java 10:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ java -version\njava version \"10.0.2\" 2018-07-17<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><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>Java 11:<\/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\">$ java -version\njava version \"11.0.11\" 2021-04-20 LTS<\/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>Bis heute gab es keine weitere \u00c4nderung am Versionsschema.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"parallel-full-gc-for-g1\">Parallel Full GC for G1<\/h2>\n\n\n\n<p>Mit dem JDK 9 hat der <a rel=\"noopener\" href=\"https:\/\/docs.oracle.com\/javase\/9\/gctuning\/garbage-first-garbage-collector.htm\" target=\"_blank\">Garbage-First (G1) Garbage Collector<\/a> den Parallel Collector als Standard-GC abgel\u00f6st.<\/p>\n\n\n\n<p>W\u00e4hrend der Parallel GC auch eine vollst\u00e4ndige Gargage Collection (\"Full GC\", also das Aufr\u00e4umen <em>aller<\/em> Regionen des Heaps) parallel zur laufenden Applikation durchf\u00fchren konnte, war dies beim G1 bisher nicht m\u00f6glich. Der G1 musste dazu vorr\u00fcbergehend die Application anhalten (\"Stop-the-World\"), was zu sp\u00fcrbaren Latenzen f\u00fchren konnte.<\/p>\n\n\n\n<p>Da der G1 mit dem Ziel entwickelt wurde vollst\u00e4ndige Collections so gut es geht zu vermeiden, stellte dies nur selten ein Problem dar.<\/p>\n\n\n\n<p>In Java 10 wurde mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/307\" target=\"_blank\">JDK Enhancement Proposal 307<\/a> nun auch die vollst\u00e4ndige Gargage Collection des G1 Collectors parallelisiert. Die worst-case Latenzen (Pausezeiten) erreichen die des Parallel Collectors.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"application-class-data-sharing\">Application Class-Data Sharing<\/h2>\n\n\n\n<p>Da viele Java-Entwickler nicht damit vertraut sind, m\u00f6chte ich kurz ausholen und <em>Class-Data Sharing<\/em> (also ohne den \"Application\"-Prefix) erkl\u00e4ren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"class-data-sharing\">Class-Data Sharing<\/h3>\n\n\n\n<p>Wenn eine JVM startet, l\u00e4dt sie die JDK-Klassenbibliothek aus dem Dateisystem (bis JDK 8 aus der Datei <code>jre\/lib\/rt.jar<\/code>; seit JDK 9 aus den <code>jmod<\/code>-Dateien im <code>jmods<\/code>-Verzeichnis). Dabei werden die <code>class<\/code>-Dateien aus den Archiven extrahiert, in eine architekturspezifische bin\u00e4re Form gebracht und im Arbeitsspeicher des JVM-Prozesses abgelegt:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_600\"><img decoding=\"async\" width=\"600\" height=\"324\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4-600x324.png\" alt=\"Laden der JDK-Klassenbibliothek ohne Class-Data Sharing \u2013 eine JVM\" class=\"wp-image-23250\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4-600x324.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4-224x121.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4-336x181.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4-504x272.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4-672x363.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4-400x216.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4-800x432.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4-944x510.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-single-JVM-v4.png 1200w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">Laden der JDK-Klassenbibliothek ohne Class-Data Sharing \u2013 eine JVM<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Werden auf derselben Maschine mehrere JVMs gestartet, wiederholt sich dieser Prozess. Jede JVM h\u00e4lt ihre eigene Kopie der Klassenbibliothek im RAM:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_600\"><img decoding=\"async\" width=\"600\" height=\"405\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3-600x405.png\" alt=\"Laden der JDK-Klassenbibliothek ohne Class-Data Sharing \u2013 mehrere JVMs\" class=\"wp-image-23248\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3-600x405.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3-224x151.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3-336x227.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3-504x340.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3-672x454.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3-400x270.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3-800x540.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3-944x637.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Without-Class-Data-Sharing-multiple-JVMs-v3.png 1200w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">Laden der JDK-Klassenbibliothek ohne Class-Data Sharing \u2013 mehrere JVMs<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Mit Class-Data Sharing (\"CDS\") werden zwei Ziele verfolgt:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Die Start-Zeit der JVM soll verk\u00fcrzt werden.<\/li>\n\n\n\n<li>Der Memory-Footprint (auf deutsch: der Speicherbedarf) der JVM soll reduziert werden.<\/li>\n<\/ol>\n\n\n\n<p>Class-Data Sharing funktioniert wie folgt:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Mit dem Kommando <code>java -Xshare:dump<\/code> wird einmalig eine Datei <code>classes.jsa<\/code> (JSA steht f\u00fcr Java Shared Archive) erzeugt. Diese enth\u00e4lt die komplette Klassenbibliothek im Bin\u00e4rformat der aktuellen Architektur.<\/li>\n\n\n\n<li>Beim Start der JVM wird diese Datei per <a rel=\"noopener\" href=\"https:\/\/de.wikipedia.org\/wiki\/Memory_Mapped_I\/O\" target=\"_blank\">Memory Mapped I\/O<\/a> durch das Betriebssystem in den Arbeitsspeicher der JVM \"gemappt\". Das ist erstens schneller als das Laden der jar- bzw. jmod-Dateien. Und zweitens l\u00e4dt das Betriebssystem die Datei nur ein einziges Mal in den RAM und stellt jedem JVM-Prozess eine Read-Only-Sicht auf denselben Speicherbereich zur Verf\u00fcgung.<\/li>\n<\/ol>\n\n\n\n<p>Die folgende Grafik soll dies verdeutlichen:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"403\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-800x403.png\" alt=\" Laden der JDK-Klassenbibliothek mit Class-Data Sharing\" class=\"wp-image-23211\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-800x403.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-224x113.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-336x169.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-504x254.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-672x339.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-400x202.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-600x302.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-944x476.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs-1200x605.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Class-Data-Sharing-multiple-JVMs.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\"> Laden der JDK-Klassenbibliothek mit Class-Data Sharing<\/figcaption><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"application-class-data-sharing-schritt-fuer-schritt\">Application Class-Data Sharing \u2013 Schritt f\u00fcr Schritt<\/h3>\n\n\n\n<p>Application Class-Data Sharing (auch \"Application CDS\" oder \"AppCDS\") erweitert CDS um die M\u00f6glichkeit neben der JDK-Klassenbibliothek auch die Klassen deiner Applikation in einer JSA-Datei zu speichern und diese unter den JVM-Prozessen zu teilen.<\/p>\n\n\n\n<p>Wie das funktioniert, zeige ich dir an einem einfachen Beispiel (du findest den Quellcode auch in diesem <a href=\"https:\/\/github.com\/SvenWoltmann\/application-cds-demo\" target=\"_blank\" rel=\"noopener\">GitHub-Repository<\/a>):<\/p>\n\n\n\n<p>Im Verzeichnis <code>src\/eu\/happycoders\/appcds<\/code> liegen folgende zwei Java-Dateien:<\/p>\n\n\n\n<p><code>Main.java<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"GLSL\" data-shcb-language-slug=\"glsl\"><span><code class=\"hljs language-glsl\">package eu.happycoders.appcds;\n\npublic class Main {\n  public static <span class=\"hljs-type\">void<\/span> main(String&#091;] args) {\n    new Greeter().greet();\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">GLSL<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">glsl<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><code>Greeter.java<\/code>:<\/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\">package<\/span> eu.happycoders.appcds;\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Greeter<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">greet<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    System.out.println(<span class=\"hljs-string\">\"Hello world!\"<\/span>);\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Wir compilieren und paketieren die Klassen wie folgt und starten dann die Main-Klasse:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">javac -d target\/classes src\/eu\/happycoders\/appcds\/*.java\njar cf target\/helloworld.jar -C target\/classes .\n\njava -cp target\/helloworld.jar eu.happycoders.appcds.Main<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Wir sollten nun die \"Hello World!\"-Begr\u00fc\u00dfung auf der Kommandozeile sehen.<\/p>\n\n\n\n<p>Um Application CDS einzusetzen, m\u00fcssen wir als n\u00e4chstes eine Liste der Klassen erstellen, die die Applikation verwendet. Dazu f\u00fchren wir folgendes Kommando aus (unter Windows musst du die Backslashes weglassen und alles in eine Zeile schreiben):<\/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\">java -Xshare:off -XX:+UseAppCDS \\\n    -XX:DumpLoadedClassList=helloworld.lst \\\n    -cp target\/helloworld.jar eu.happycoders.appcds.Main<\/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>Achtung: Dieses Kommando funktioniert so nur im OpenJDK. Im Oracle JDK wirst du den Hinweis erhalten, dass Application CDS ein kommerzielles Feature ist, das du zun\u00e4chst mit <code>-XX:+UnlockCommercialFeatures<\/code> freischalten musst. Also am besten OpenJDK verwenden!<\/p>\n\n\n\n<p>Im Arbeitsverzeichnis sollte sich jetzt die Datei <code>helloworld.lst<\/code> mit in etwa folgendem Inhalt befinden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">java\/lang\/Object\njava\/lang\/String\n...\neu\/happycoders\/appcds\/Main\neu\/happycoders\/appcds\/Greeter\n...\njava\/lang\/Shutdown\njava\/lang\/Shutdown$Lock<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><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>Wie du siehst, werden nicht nur die Klassen der Applikation aufgelistet, sondern auch die der JDK-Klassenbibliothek.<\/p>\n\n\n\n<p>Als n\u00e4chstes erstellen wir aus der Klassenliste die JSA-Datei.<\/p>\n\n\n\n<p>(Hinweis: W\u00e4hrend man in den vorherigen Schritten als Classpath auch das Verzeichnis <code>target\/classes<\/code> h\u00e4tte angeben k\u00f6nnen, funktioniert der folgende Schritt nur mit der paketierten <code>helloworld.jar<\/code>-Datei.)<\/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 -Xshare:dump -XX:+UseAppCDS \\\n    -XX:SharedClassListFile=helloworld.lst \\\n    -XX:SharedArchiveFile=helloworld.jsa \\\n    -cp target\/helloworld.jar<\/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>Du bekommst w\u00e4hrend der Verarbeitung einige Statistiken angezeigt und findest anschlie\u00dfend die Datei <code>helloworld.jsa<\/code> im Arbeitsverzeichnis. Sie sollte etwa 9 MB gro\u00df sein.<\/p>\n\n\n\n<p>Um die JSA-Datei zu verwenden, startest du die Anwendung nun wie folgt:<\/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\">java -Xshare:on -XX:+UseAppCDS \\\n    -XX:SharedArchiveFile=helloworld.jsa \\\n    -cp target\/helloworld.jar eu.happycoders.appcds.Main<\/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>Wenn alles funktioniert hat, solltest du erneut ein \"Hello world!\" sehen.<\/p>\n\n\n\n<p>Folgende Grafik fasst die Funktionsweise von Application Class-Data Sharing zusammen:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"453\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-800x453.png\" alt=\"Application Class Data Sharing (&quot;AppCDS&quot;)\" class=\"wp-image-23216\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-800x453.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-224x127.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-336x190.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-504x285.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-672x381.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-400x227.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-600x340.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-944x535.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing-1200x680.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Application-Class-Data-Sharing.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Application Class Data Sharing (\"AppCDS\")<\/figcaption><\/figure>\n<\/div>\n\n\n<p><em>(Application CDS ist im <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/310\" target=\"_blank\">Java Enhancement Proposal 310<\/a> definiert.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"experimental-java-based-jit-compiler\">Experimental Java-Based JIT Compiler<\/h2>\n\n\n\n<p>Seit Java 9 wird der <a rel=\"noopener\" href=\"https:\/\/www.graalvm.org\/reference-manual\/compiler\/\" target=\"_blank\">Graal Compiler<\/a> (ein in Java geschriebener Java-Compiler) als experimenteller Ahead-of-Time (AOT)-Compiler mit ausgeliefert. Dieser erm\u00f6glicht es ein Java-Programm in eine nativ ausf\u00fchrbare Datei (also z. B. eine exe-Datei unter Windows) zu compilieren.<\/p>\n\n\n\n<p>In Java 10 wurde mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/317\" target=\"_blank\">JEP 317<\/a> die M\u00f6glichkeit geschaffen, Graal auch als Just-in-Time (JIT)-Compiler einzusetzen \u2013 zumindest auf der Linux\/x64-Plattform. Dazu verwendet Graal das im JDK 9 eingef\u00fchrte JVM Compiler Interface (JVMCI).<\/p>\n\n\n\n<p>Aktiviert wird Graal \u00fcber die folgende  Option in der java-Befehlszeile:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler<\/code><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sonstige-aenderungen-in-java-10-die-man-als-java-entwickler-nicht-unbedingt-kennen-muss\">Sonstige \u00c4nderungen in Java 10 (die man als Java-Entwickler nicht unbedingt kennen muss)<\/h2>\n\n\n\n<p>In diesem Abschnitt liste ich diejenigen Java 10 Features auf, von denen ich denke, dass nicht jeder Java-Entwickler im Detail \u00fcber sie Bescheid wissen muss.<\/p>\n\n\n\n<p>Andererseits schadet es nicht, wenigstens einmal von ihnen geh\u00f6rt zu haben. :-)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"heap-allocation-on-alternative-memory-devices\">Heap Allocation on Alternative Memory Devices<\/h3>\n\n\n\n<p>Mit Umsetzung des <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/316\" target=\"_blank\">JEP 316<\/a> kann der Java-Heap \u2013 statt auf herk\u00f6mmlichem RAM \u2013 auch auf einem alternativen Speicherger\u00e4t, z. B. auf NV-DIMM (nicht-fl\u00fcchtigem Speicher) angelegt werden.<\/p>\n\n\n\n<p>Der alternative Speicher muss dazu vom Betriebssystem \u00fcber einen Dateisystem-Pfad zur Verf\u00fcgung gestellt werden (z. B. <code>\/dev\/pmem0<\/code>) und wird \u00fcber folgende Option in der java-Befehlszeile eingebunden:<\/p>\n\n\n\n<p class=\"has-text-align-center\"> <code>-XX:AllocateHeapAt=&lt;path&gt;<\/code><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"additional-unicode-language-tag-extensions\">Additional Unicode Language-Tag Extensions<\/h3>\n\n\n\n<p>Mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/314\" target=\"_blank\">JEP 314<\/a> werden sogenannte \"Language-Tag Extensions\" hinzugef\u00fcgt. Diese erm\u00f6glichen es in einem <code>Locale<\/code>-Objekt folgende Zusatzinformationen zu hinterlegen:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th>Schl\u00fcssel<\/th><th>Bezeichnung englisch<\/th><th>Bezeichnung deutsch<\/th><th>Beispiele<\/th><\/tr><\/thead><tbody><tr><td>cu<\/td><td>Currency<\/td><td>W\u00e4hrung<\/td><td>ISO 4217 W\u00e4hrungscodes<\/td><\/tr><tr><td>fw<\/td><td>First day of week<\/td><td>Erster Tag der Woche<\/td><td>sun (Sonntag), mon (Montag)<\/td><\/tr><tr><td>rg<\/td><td>Region override<\/td><td>\u00dcberschreibung der Region<\/td><td>uszzzz (US-Einheiten)<\/td><\/tr><tr><td>tz<\/td><td>Timezone<\/td><td>Zeitzone<\/td><td>deber (Berlin), uslax (Los Angeles)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Die folgenden zwei Extensions existieren bereits seit Java 7:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th>Schl\u00fcssel<\/th><th>Bezeichnung englisch<\/th><th>Bezeichnung deutsch<\/th><th>Beispiele<\/th><\/tr><\/thead><tbody><tr><td>ca<\/td><td>Calendar<\/td><td>Kalendar<\/td><td>gregorian, buddhist, chinese<\/td><\/tr><tr><td>nu<\/td><td>Numbering system<\/td><td>Zahlensystem<\/td><td>arab, roman<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Der folgende Beispiel-Quellcode zeigt die Erstellung einer deutschen Locale (\"de-DE\") mit US-Dollar als W\u00e4hrung (\"cu-usd\"), Mittwoch als erstem Tag der Woche (\"fw-wed\") und der Zeitzone von Los Angeles (\"tz-uslax\"):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">Locale locale = Locale.forLanguageTag(<span class=\"hljs-string\">\"de-DE-u-cu-usd-fw-wed-tz-uslax\"<\/span>);\n\nCurrency currency = Currency.getInstance(locale);\n\nCalendar calendar = Calendar.getInstance(locale);\nDayOfWeek firstDayOfWeek = DayOfWeek.of((calendar.getFirstDayOfWeek() + <span class=\"hljs-number\">5<\/span>) % <span class=\"hljs-number\">7<\/span> + <span class=\"hljs-number\">1<\/span>);\n\nDateFormat dateFormat = DateFormat.getTimeInstance(LONG, locale);\nString time = dateFormat.format(<span class=\"hljs-keyword\">new<\/span> Date());\n\nSystem.out.println(<span class=\"hljs-string\">\"currency       = \"<\/span> + currency);\nSystem.out.println(<span class=\"hljs-string\">\"firstDayOfWeek = \"<\/span> + firstDayOfWeek);\nSystem.out.println(<span class=\"hljs-string\">\"time           = \"<\/span> + time);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Zum Zeitpunkt des Schreibens dieses Artikels (20:45 Uhr in Berlin) gibt das Beispiel-Programm folgendes aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">currency       = USD\nfirstDayOfWeek = WEDNESDAY\ntime           = 11:45:50 PDT<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><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>Unter Java 9 werden die zus\u00e4tzlichen Tags ignoriert, und das Programm gibt (40 Sekunden sp\u00e4ter) folgendes aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">currency       = EUR\nfirstDayOfWeek = MONDAY\ntime           = 20:46:30 MESZ<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><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>Da sich vermutlich nur sehr wenige Java-Entwickler mit solchen Details besch\u00e4ftigen m\u00fcssen, habe ich diese Erweiterung unter \"Sonstiges\" einsortiert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"garbage-collector-interface\">Garbage Collector Interface<\/h3>\n\n\n\n<p>Einige Teile der Quellcodes der Garbage Collectoren liegen bis Java 9 in langen <code>if<\/code>-<code>else<\/code>-Ketten tief in den Quellcodes des Java-Interpreters und des C1- und C2-Compilers verborgen. Um einen neuen Garbage Collector zu implementieren, mussten Entwickler all diese Stellen kennen und f\u00fcr ihre spezifischen Anforderungen erweitern.<\/p>\n\n\n\n<p>Durch den <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/304\" target=\"_blank\">JDK Enhancement Proposal 304<\/a> wird im JDK-Quellcode eine saubere Garbage-Collector-Schnittstelle eingef\u00fchrt und damit die Algorithmen der Garbage Collectoren vom Interpreter und den Compilern isoliert.<\/p>\n\n\n\n<p>So k\u00f6nnen Entwickler in Zukunft neue GCs hinzuf\u00fcgen, ohne die Codebasis des Interpreters und Compilers angepassen zu m\u00fcssen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"root-certificates\">Root Certificates<\/h3>\n\n\n\n<p>Bis zu Java 9 enthielt das OpenJDK in der Keystore-Datei <code>cacerts<\/code> keine Root-Zertifikate, so dass SSL\/TLS-basierte Features nicht ohne weiteres lauff\u00e4hig waren.<\/p>\n\n\n\n<p>Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/319\" target=\"_blank\">JDK Enhancement Proposal 319<\/a> wurden die im Oracle-JDK enthaltenen Root-Zertifikate in das OpenJDK \u00fcbernommen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"thread-local-handshakes\">Thread-Local Handshakes<\/h3>\n\n\n\n<p>Thread-Local Handshakes sind eine Optimierung, um die VM-Leistung auf x64- und SPARC-basierten Architekturen zu verbessern. Die Optimierung ist per default aktiviert. Details findest du im <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/312\" target=\"_blank\">JDK Enhancement Proposal 312<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"remove-the-native-header-generation-tool\">Remove the Native-Header Generation Tool<\/h3>\n\n\n\n<p>Mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/313\" target=\"_blank\">JEP 313<\/a> wurde das Tool <code>javah<\/code> entfernt, mit dem man native Header-Dateien f\u00fcr JNI erzeugen konnte. Die Funktionalit\u00e4t wurde in den Java-Compiler, <code>javac<\/code>, integriert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"consolidate-the-jdk-forest-into-a-single-repository\">Consolidate the JDK Forest into a Single Repository<\/h3>\n\n\n\n<p>Im JDK 9 lag der Quellcode in acht separaten Mercurial-Repositories, was bei der Entwicklung oft zu einem erheblichen Mehraufwand f\u00fchrte. Bei \u00fcber tausend \u00c4nderungen war es erforderlich logisch zusammenh\u00e4ngende Commits \u00fcber mehrere Repositories zu verteilen.<\/p>\n\n\n\n<p>Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/296\" target=\"_blank\">JEP 296<\/a> wurde der gesamte JDK-Quellcode in ein <a href=\"\/de\/software-craftsmanship\/monorepo-vor-und-nachteile\/\">Monorepo<\/a> konsolidiert. Die Verwendung eines Monorepos erlaubt nun atomare Commits, Branches und Pull Requests, was die Arbeit am JDK deutlich erleichtert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vollstaendige-liste-aller-aenderungen-in-java-10\">Vollst\u00e4ndige Liste aller \u00c4nderungen in Java 10<\/h3>\n\n\n\n<p>Dieser Artikel hat alle Features von Java 10 vorgestellt, die in JDK Enhancement Proposals definiert sind, sowie Erweiterungen an der JDK-Klassenbibliothek, die keinem JEP zugeordnet sind.<\/p>\n\n\n\n<p>Eine vollst\u00e4ndige Liste aller \u00c4nderungen findest du in den&nbsp;<a rel=\"noopener\" href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/10-relnote-issues.html\" target=\"_blank\">offiziellen Java 10 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>Mit <code>var<\/code>, Immutable Collections und <code>Optional.orElseThrow()<\/code> hat Java 10 uns einige hilfreiche neue Werkzeuge bereitgestellt. Der G1 Garbage Collector arbeitet jetzt nahezu komplett parallel. Und mit Application Class-Data Sharing k\u00f6nnen wir den Start unserer Applikation weiter beschleunigen und den Memory Footprint reduzieren. Wer Lust am experimentieren hat, kann den in Java geschriebenen Graal-Compiler aktivieren.<\/p>\n\n\n\n<p>Wenn dir der Artikel gefallen hat, hinterlasse mir gerne einen Kommentar oder teile den Artikel \u00fcber einen der Share-Buttons am Ende. M\u00f6chtest du informiert werden, wenn der n\u00e4chste Artikel auf HappyCoders ver\u00f6ffentlicht wird? Dann <a href=\"#\" data-formkit-toggle=\"d8ee997126\">klicke hier<\/a>, um dich f\u00fcr den <a href=\"#\" data-formkit-toggle=\"135d38e6d4\">HappyCoders-Newsletter<\/a> anzumelden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Alle neuen Features von Java 10: \"var\", Immutable Collections, Optional.orElseThrow(), Application Class-Data Sharing und mehr.<\/p>\n","protected":false},"author":1,"featured_media":34286,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_titles_title":"","_seopress_titles_desc":"Alle neuen Features von Java 10 mit Beispielen: \"var\", Immutable Collections, Optional.orElseThrow(), Application Class-Data Sharing und 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 10 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":21866,"_post_count":0,"footnotes":""},"categories":[64],"tags":[176],"class_list":["post-23022","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\/2021\/10\/java-10-features.jpg",1770,986,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features.jpg",150,84,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features.jpg",768,428,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features.jpg",1024,570,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-224x125.jpg",224,125,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-504x281.jpg",504,281,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-672x374.jpg",672,374,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-400x223.jpg",400,223,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-600x334.jpg",600,334,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-800x446.jpg",800,446,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-944x526.jpg",944,526,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-1200x668.jpg",1200,668,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features-1770x735.jpg",1770,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-features.jpg",1536,856,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-10-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":"Alle neuen Features von Java 10: \"var\", Immutable Collections, Optional.orElseThrow(), Application Class-Data Sharing und mehr.","public_identification_id":"3f61b00a2f4c4925ad4b51b4114a26b4","private_identification_id":"8dc804bfa5d242f8a51c6436c38341f5","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/23022","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=23022"}],"version-history":[{"count":10,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/23022\/revisions"}],"predecessor-version":[{"id":39775,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/23022\/revisions\/39775"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/34286"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=23022"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=23022"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=23022"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}