{"id":23301,"date":"2021-10-26T14:45:13","date_gmt":"2021-10-26T12:45:13","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=23301"},"modified":"2024-11-27T14:59:55","modified_gmt":"2024-11-27T13:59:55","slug":"java-11-features","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/java-11-features\/","title":{"rendered":"Java 11 Features (mit Beispielen)"},"content":{"rendered":"\n<p>Mit Java 11 wurde am 25. September 2018 das erste Long-Term-Support (LTS)-Release des JDK seit der Umstellung auf den sechsmonatige Release-Zyklus ver\u00f6ffentlicht. \"Long-Term-Support\" bedeutet, dass Oracle diese Version f\u00fcr mehrere Jahre mit Sicherheitspatches ausstatten wird.<\/p>\n\n\n\n<p>Die letzte LTS-Version war Java 8. Java 9 und 10 waren <em>keine<\/em> LTS-Releases, was bedeutet, dass der Support dieser Versionen mit der jeweils folgenden Version eingestellt wurde.<\/p>\n\n\n\n<p>Ich habe die \u00c4nderungen in Java 11 nach Relevanz f\u00fcr die t\u00e4gliche Entwicklerarbeit sortiert. Zuerst kommen \u00c4nderungen an der Sprache selbst. Es folgen Erweiterungen an der JDK-Klassenbibliothek, Tools und experimentelle Features. Und zuletzt Deprecations, L\u00f6schungen und sonstige kleine \u00c4nderungen.<\/p>\n\n\n\n<p>Wichtig ist noch zu wissen, dass das Oracle-JDK ab Version 11 nur noch f\u00fcr Entwickler frei nutzbar ist. Firmen ben\u00f6tigen einen kostenpflichtigen Supportvertrag mit Oracle. <em>Open<\/em>JDK 11 hingegen ist f\u00fcr alle frei einsetzbar.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"local-variable-syntax-for-lambda-parameters\">Local-Variable Syntax for Lambda Parameters<\/h2>\n\n\n\n<p>Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/323\" target=\"_blank\">JDK Enhancement Proposal 323<\/a> wird die Verwendung von \"var\" in Parametern von implizit typisierten Lambda-Ausdr\u00fccken erlaubt.<\/p>\n\n\n\n<p>Was ist ein <em>implizit typisierter<\/em> Lambda-Ausdruck?<\/p>\n\n\n\n<p>Fangen wir mit einem <em>explizit<\/em> typisierten Lambda-Ausdruck an. <em>Explizit<\/em> bedeutet in folgendem Beispiel, dass die Datentypen der Lambda-Parameter <code>l<\/code> und <code>s<\/code> \u2013 also <code>List&lt;String&gt;<\/code> und <code>String<\/code> \u2013 mit angegeben sind:<\/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; l, String s) -&gt; l.add(s);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Der Compiler kann die Typen allerdings auch aus dem Kontext herleiten, so dass auch folgende \u2013 <em>implizit<\/em> typisierte \u2013 Schreibweise erlaubt ist:<\/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\">(l, s) -&gt; l.add(s);<\/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>Seit Java 11 kann anstelle der expliziten Typen auch das <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-10-features\/#Local-Variable_Type_Inference_var\">in Java 10 eingef\u00fchrte \"var\"<\/a> verwendet 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-keyword\">var<\/span> l, <span class=\"hljs-keyword\">var<\/span> s) -&gt; l.add(s);<\/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>Doch warum sollte man \"var\" schreiben, wenn man die Typen, wie im Beispiel davor, komplett weglassen kann?<\/p>\n\n\n\n<p>Der Grund daf\u00fcr sind Annotationen. Soll eine Variable annotiert werden, muss die Annotation am Typ stehen \u2013 das kann ein expliziter Typ sein oder auch \"var\". Eine Annotation direkt am Variablennamen ist nicht erlaubt.<\/p>\n\n\n\n<p>M\u00f6chte man die Variablen im obigen Beispiel-Lambda annotieren, war bisher nur folgende Schreibweise m\u00f6glich:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">(<span class=\"hljs-meta\">@Nonnull<\/span> List&lt;String&gt; l, <span class=\"hljs-meta\">@Nullable<\/span> String s) -&gt; l.add(s);<\/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>Java 11 erlaubt mit \"var\" nun auch folgende, k\u00fcrzere Variante:<\/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-meta\">@Nonnull<\/span> <span class=\"hljs-keyword\">var<\/span> l, <span class=\"hljs-meta\">@Nullable<\/span> <span class=\"hljs-keyword\">var<\/span> s) -&gt; l.add(s);<\/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 verschiedenen Schreibweisen d\u00fcrfen nicht gemischt werden. D. h. du musst entweder f\u00fcr alle Variablen den Typ angeben, alle Typen weglassen oder bei allen Variablen \"var\" verwenden.<\/p>\n\n\n\n<p>Welche Form du letztendlich w\u00e4hlst, h\u00e4ngt von der Lesbarkeit im konkreten Fall und den Stil-Vorgaben deines Teams ab.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"http-client-standard\">HTTP Client (Standard)<\/h2>\n\n\n\n<p>Um vor Java 11 mit JDK-Hausmitteln Daten z. B. per HTTP-POST zu versenden, war eine ganze Menge Code erforderlich.<\/p>\n\n\n\n<p>(Das folgende Beispiel verwendet dabei das in Java 8 hinzugekommene <code>BufferedReader.lines()<\/code>, um die Antwort als Stream zu lesen und per Collector zu einem String zusammenzufassen. Vor Java 8 waren hierf\u00fcr noch einige Zeilen mehr n\u00f6tig.)<\/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-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">post<\/span><span class=\"hljs-params\">(String url, String data)<\/span> <span class=\"hljs-keyword\">throws<\/span> IOException <\/span>{\n  URL urlObj = <span class=\"hljs-keyword\">new<\/span> URL(url);\n  HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();\n  con.setRequestMethod(<span class=\"hljs-string\">\"POST\"<\/span>);\n  con.setRequestProperty(<span class=\"hljs-string\">\"Content-Type\"<\/span>, <span class=\"hljs-string\">\"application\/json\"<\/span>);\n\n  <span class=\"hljs-comment\">\/\/ Send data<\/span>\n  con.setDoOutput(<span class=\"hljs-keyword\">true<\/span>);\n  <span class=\"hljs-keyword\">try<\/span> (OutputStream os = con.getOutputStream()) {\n    <span class=\"hljs-keyword\">byte<\/span>&#091;] input = data.getBytes(StandardCharsets.UTF_8);\n    os.write(input, <span class=\"hljs-number\">0<\/span>, input.length);\n  }\n\n  <span class=\"hljs-comment\">\/\/ Handle HTTP errors<\/span>\n  <span class=\"hljs-keyword\">if<\/span> (con.getResponseCode() != <span class=\"hljs-number\">200<\/span>) {\n    con.disconnect();\n    <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IOException(<span class=\"hljs-string\">\"HTTP response status: \"<\/span> + con.getResponseCode());\n  }\n\n  <span class=\"hljs-comment\">\/\/ Read response<\/span>\n  String body;\n  <span class=\"hljs-keyword\">try<\/span> (InputStreamReader isr = <span class=\"hljs-keyword\">new<\/span> InputStreamReader(con.getInputStream());\n      BufferedReader br = <span class=\"hljs-keyword\">new<\/span> BufferedReader(isr)) {\n    body = br.lines().collect(Collectors.joining(<span class=\"hljs-string\">\"\\n\"<\/span>));\n  }\n  con.disconnect();\n\n  <span class=\"hljs-keyword\">return<\/span> body;\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>Das JDK 11 enth\u00e4lt die neue Klasse <a rel=\"noopener\" href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/11\/docs\/api\/java.net.http\/java\/net\/http\/HttpClient.html\" target=\"_blank\">HttpClient<\/a>, die die Arbeit mit HTTP wesentlich vereinfacht.<\/p>\n\n\n\n<p>Den Code oben kann man mit <code>HttpClient<\/code> deutlich k\u00fcrzer und aussagekr\u00e4ftiger schreiben:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> String <span class=\"hljs-title\">post<\/span><span class=\"hljs-params\">(String url, String data)<\/span> <span class=\"hljs-keyword\">throws<\/span> IOException, InterruptedException <\/span>{\n  HttpClient client = HttpClient.newHttpClient();\n\n  HttpRequest request =\n      HttpRequest.newBuilder()\n          .uri(URI.create(url))\n          .header(<span class=\"hljs-string\">\"Content-Type\"<\/span>, <span class=\"hljs-string\">\"application\/json\"<\/span>)\n          .POST(BodyPublishers.ofString(data))\n          .build();\n\n  HttpResponse&lt;String&gt; response = client.send(request, BodyHandlers.ofString());\n\n  <span class=\"hljs-keyword\">if<\/span> (response.statusCode() != <span class=\"hljs-number\">200<\/span>) {\n    <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IOException(<span class=\"hljs-string\">\"HTTP response status: \"<\/span> + response.statusCode());\n  }\n\n  <span class=\"hljs-keyword\">return<\/span> response.body();\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>Die neue <code>HttpClient<\/code>-Klasse ist vielseitig einsetzbar:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u00dcber <code>BodyPublishers.ofString()<\/code> senden wir im Beispiel oben einen String. \u00dcber die Methoden <code>ofByteArray()<\/code>, <code>ofByteArrays()<\/code>, <code>ofFile()<\/code> und <code>ofInputStream()<\/code> der gleichen Klasse k\u00f6nnen wir die zu sendenden Daten auch aus anderen Quellen lesen.<\/li>\n\n\n\n<li>Analog kann die Klasse <code>BodyHandlers<\/code>, mit deren <code>ofString()<\/code>-Methode wir die Antwort als String geliefert bekommen, auch Byte-Arrays und Streams liefern oder die empfangene Antwort in einer Datei speichern.<\/li>\n\n\n\n<li><code>HttpClient<\/code> unterst\u00fctzt im Gegensatz zur bisherigen L\u00f6sung auch HTTP\/2 and WebSocket.<\/li>\n\n\n\n<li>Au\u00dferdem bietet <code>HttpClient<\/code> neben dem oben gezeigten synchronen Programmiermodell auch ein asynchrones Modell. Die Methode <code>HttpClient.sendAsync()<\/code> gibt dabei ein <code>CompletableFuture<\/code> zur\u00fcck, mit dem wir dann asynchron weiterarbeiten k\u00f6nnen.<\/li>\n<\/ul>\n\n\n\n<p>Eine asynchrone Variante der Post-Methode kann z. B. wie folgt aussehen:<\/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> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">postAsync<\/span><span class=\"hljs-params\">(\n    String url, String data, Consumer&lt;String&gt; consumer, IntConsumer errorHandler)<\/span> <\/span>{\n  HttpClient client = HttpClient.newHttpClient();\n\n  HttpRequest request =\n      HttpRequest.newBuilder()\n          .uri(URI.create(url))\n          .header(<span class=\"hljs-string\">\"Content-Type\"<\/span>, <span class=\"hljs-string\">\"application\/json\"<\/span>)\n          .POST(BodyPublishers.ofString(data))\n          .build();\n\n  client\n      .sendAsync(request, BodyHandlers.ofString())\n      .thenAccept(\n          response -&gt; {\n            <span class=\"hljs-keyword\">if<\/span> (response.statusCode() == <span class=\"hljs-number\">200<\/span>) {\n              consumer.accept(response.body());\n            } <span class=\"hljs-keyword\">else<\/span> {\n              errorHandler.accept(response.statusCode());\n            }\n          });\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><em>(HttpClient ist definiert im&nbsp;<a href=\"https:\/\/openjdk.org:443\/jeps\/321\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 321<\/a>.)<\/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=\"neue-collection-toarray-methode\">Neue Collection.toArray()-Methode<\/h2>\n\n\n\n<p>Bisher bot das <code>Collection<\/code>-Interface zwei <code>toArray()<\/code>-Methoden, um Collections in Arrays zu konvertieren. Das folgende Beispiel zeigt diese zwei Methoden (und zwei unterschiedliche Anwendungen der zweiten Methode) am Beispiel einer Liste von Strings:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Gherkin\" data-shcb-language-slug=\"gherkin\"><span><code class=\"hljs language-gherkin\">List<span class=\"hljs-variable\">&lt;String&gt;<\/span> list = List.of(<span class=\"hljs-string\">\"foo\"<\/span>, <span class=\"hljs-string\">\"bar\"<\/span>, <span class=\"hljs-string\">\"baz\"<\/span>);\n\nObject&#091;] strings1 = list.toArray();\n\nString&#091;] strings2a = list.toArray(new String&#091;list.size()]);\nString&#091;] strings2b = list.toArray(new String&#091;0]);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Gherkin<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">gherkin<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Die erste <code>toArray()<\/code>-Methode ohne Parameter liefert ein Objekt-Array zur\u00fcck, da aufgrund von Type Erasure zur Laufzeit die Typ-Information von <code>list<\/code> nicht mehr bekannt ist.<\/p>\n\n\n\n<p>Der zweiten <code>toArray()<\/code>-Methode \u00fcbergeben wir ein Array des gew\u00fcnschten Typs. Wenn dieses Array mindestens so gro\u00df ist wie die Collection, werden die Elemente in diesem Array hinterlegt (<code>strings2a<\/code>). Andernfalls wird ein neues Array in der erforderlichen Gr\u00f6\u00dfe erstellt (<code>strings2b<\/code>).<\/p>\n\n\n\n<p>Seit Java 12 k\u00f6nnen wir auch folgendes 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\">String&#091;] strings = list.toArray(String&#091;]::<span class=\"hljs-keyword\">new<\/span>);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Diese Methode erlaubt es den <code>Collection<\/code>-Klassen anhand der \u00fcbergebenen Referenz auf den Array-Konstruktor selbst ein Array der ben\u00f6tigten Gr\u00f6\u00dfe zu erstellen.<\/p>\n\n\n\n<p>Allerdings wird diese M\u00f6glichkeit nicht (oder selten?) genutzt. Die Methode ist lediglich im <code>Collection<\/code>-Interface implementiert. Sie erstellt ein leeres Array und ruft dann die bisherige <code>toArray()<\/code>-Methode auf:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">default<\/span> &lt;T&gt; T&#091;] toArray(IntFunction&lt;T&#091;]&gt; generator) {\n  <span class=\"hljs-keyword\">return<\/span> toArray(generator.apply(<span class=\"hljs-number\">0<\/span>));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ich habe nicht alle <code>Collection<\/code>-Implementierungen untersucht. Aber alle, die ich mir angeschaut haben, \u00fcberschreiben diese neue Methode <em>nicht<\/em>. Wenn du eine <code>Collection<\/code>-Klasse kennst, die diese Methode \u00fcberschreibt, schreib mir gerne einen Kommentar.<\/p>\n\n\n\n<p><em>(Die neue toArray()-Methode ist nicht in einem JDK Enhancement Proposal definiert.)<\/em> <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"neue-string-methoden\">Neue String-Methoden<\/h2>\n\n\n\n<p>In Java 11 wurde die Klasse <code>String<\/code> um einige hilfreiche Methoden erweitert:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">String.strip(), stripLeading(), stripTailing()<\/h4>\n\n\n\n<p>Die Methode <code>String.strip()<\/code> entfernt aus einem String alle f\u00fchrenden und abschlie\u00dfenden Leerzeichen.<\/p>\n\n\n\n<p>Haben wir daf\u00fcr nicht schon die Methode <code>String.trim()<\/code>?<\/p>\n\n\n\n<p>Ja, mit dem folgenden Unterschied:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>trim()<\/code> entfernt alle Zeichen, deren Codepoint U+0020 oder kleiner ist. Das schlie\u00dft z. B. \"Space\", \"Tab\", \"Newline\" und \"Carriage Return\" ein.<\/li>\n\n\n\n<li><code>strip()<\/code> entfernt diejenigen Zeichen, die <code>Character.isWhitespace()<\/code> als Leerzeichen einstuft. Das sind zum einen einige (aber nicht alle) Zeichen mit Codepoint U+0020 oder kleiner. Und zum andere Zeichen, die im Unicode-Standard als Leerzeichen, Zeilenumbr\u00fcche und Absatztrennzeichen definiert sind (z. B. U+2002 \u2013 ein Leerzeichen, das so breit ist wie der Buchstabe 'n').<\/li>\n<\/ul>\n\n\n\n<p>Es gibt noch zwei Varianten der Methode: <code>stripLeading()<\/code> entfernt nur <em>f\u00fchrende<\/em> Leerzeichen, <code>stripTailing()<\/code> nur <em>abschlie\u00dfende<\/em>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">String.isBlank()<\/h4>\n\n\n\n<p>Die Methode <code>String.isBlank()<\/code> liefert genau dann <code>true<\/code> zur\u00fcck, wenn der String nur solche Zeichen enth\u00e4lt, die das im vorangegangenen Punkt genannte <code>Character.isWhitespace()<\/code> als Leerzeichen einstuft.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">String.repeat()<\/h4>\n\n\n\n<p>Mit <code>String.repeat()<\/code> wird ein String wiederholt aneinandergereiht:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"GLSL\" data-shcb-language-slug=\"glsl\"><span><code class=\"hljs language-glsl\">System.<span class=\"hljs-keyword\">out<\/span>.println(\":-) \".repeat(<span class=\"hljs-number\">10<\/span>));\n\n\u27f6\n\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\">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<h4 class=\"wp-block-heading\">String.lines()<\/h4>\n\n\n\n<p>Die Methode <code>String.lines()<\/code> trennt einen String an Zeilenumbr\u00fcchen auf und liefert einen Stream aller Zeilen zur\u00fcck.<\/p>\n\n\n\n<p>Hier ist ein kleines Beispiel:<\/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\">Stream&lt;String&gt; lines = <span class=\"hljs-string\">\"foo\\nbar\\nbaz\"<\/span>.lines();\nlines.forEachOrdered(System.out::println);\n\n\u27f6\n\nfoo\nbar\nbaz<\/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 die Erweiterungen der String-Klasse gibt es kein JDK Enhancement Proposal.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"files-readstring-und-writestring\">Files.readString() und writeString()<\/h2>\n\n\n\n<p>Das Lesen und Schreiben von Textdateien wurde seit Java 6 kontinuierlich vereinfacht. In Java 6 mussten wir noch einen <code>FileInputStream<\/code> \u00f6ffnen, diesen mit einem <code>InputStreamReader<\/code> und einem <code>BufferedReader<\/code> wrappen, dann die Textdatei Zeile f\u00fcr Zeile in einen <code>StringBuilder<\/code> laden (oder, alternativ, den <code>BufferedReader<\/code> weglassen und die Daten in <code>char[]<\/code>-Bl\u00f6cken auslesen) und im <code>finally<\/code>-Block die <code>Reader<\/code> und den <code>InputStream<\/code> wieder schlie\u00dfen.<\/p>\n\n\n\n<p>Zum Gl\u00fcck gab es Libraries wie <a rel=\"noopener\" href=\"https:\/\/commons.apache.org\/proper\/commons-io\/\" target=\"_blank\">Apache Commons IO<\/a>, die uns mit den Methoden <code>FileUtils.readFileToString()<\/code> und <code>writeFileToString()<\/code> diese Arbeit abnahm.<\/p>\n\n\n\n<p>In Java 7 konnten wir die ineinander geschachtelte Stream\/Reader- bzw. Stream\/Writer-Kombination mit <code>Files.newBufferedWriter()<\/code> und <code>Files.newBufferedReader()<\/code> deutlich einfacher erzeugen. Und dank try-with-resources brauchten wir auch keinen <code>finally<\/code>-Block mehr.<\/p>\n\n\n\n<p>Dennoch waren noch immer mehrere Zeilen Code notwendig:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">writeStringJava7<\/span><span class=\"hljs-params\">(Path path, String text)<\/span> <span class=\"hljs-keyword\">throws<\/span> IOException <\/span>{\n  <span class=\"hljs-keyword\">try<\/span> (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {\n    writer.write(text);\n  }\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> String <span class=\"hljs-title\">readFileJava7<\/span><span class=\"hljs-params\">(Path path)<\/span> <span class=\"hljs-keyword\">throws<\/span> IOException <\/span>{\n  StringBuilder sb = <span class=\"hljs-keyword\">new<\/span> StringBuilder();\n  <span class=\"hljs-keyword\">try<\/span> (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {\n    String line;\n    <span class=\"hljs-keyword\">while<\/span> ((line = reader.readLine()) != <span class=\"hljs-keyword\">null<\/span>) {\n      sb.append(line).append(<span class=\"hljs-string\">'\\n'<\/span>);\n    }\n  }\n  <span class=\"hljs-keyword\">return<\/span> sb.toString();\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>Mit Java 11 bekommen wir endlich Methoden, die es mit denen Drittanbieter-Bibliotheken aufnehmen k\u00f6nnen:<\/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\">Files.writeString(path, text, StandardCharsets.UTF_8);\n\ntext = Files.readString(path, StandardCharsets.UTF_8);<\/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>An dieser Stelle m\u00f6chte ich ein wenig Vorfreude auf <a href=\"\/de\/java\/java-18-features\/#UTF-8_by_Default\">Java 18<\/a> wecken: <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/400\" target=\"_blank\">JEP 400<\/a> wird UTF-8 endlich als Standardzeichensatz f\u00fcr alle Architekturen und Betriebssysteme festlegen, so dass wir den Zeichensatz-Parameter dann guten Gewissens weglassen k\u00f6nnen.<\/p>\n\n\n\n<p><em>(F\u00fcr diese Erweiterung der Klassenbibliothek gibt es kein JDK Enhancement Proposal.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"path-of\">Path.of()<\/h2>\n\n\n\n<p><code>Path<\/code>-Objekte mussten wir bisher \u00fcber <code>Paths.get()<\/code> erstellen \u2013 oder <code>File.toPath()<\/code>. Die Einf\u00fchrung von default-Methoden in Interfaces in Java 8 erlaubte es den JDK-Entwicklern entsprechende Factory-Methoden direkt in das <code>Path<\/code>-Interface zu integrieren.<\/p>\n\n\n\n<p>Seit Java 11 kannst du <code>Path<\/code>-Objekte beispielsweise wie folgt erstellen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-comment\">\/\/ Relative path foo\/bar\/baz<\/span>\nPath.of(<span class=\"hljs-string\">\"foo\/bar\/baz\"<\/span>);\nPath.of(<span class=\"hljs-string\">\"foo\"<\/span>, <span class=\"hljs-string\">\"bar\/baz\"<\/span>);\nPath.of(<span class=\"hljs-string\">\"foo\"<\/span>, <span class=\"hljs-string\">\"bar\"<\/span>, <span class=\"hljs-string\">\"baz\"<\/span>);\n\n<span class=\"hljs-comment\">\/\/ Absolute path \/foo\/bar\/baz<\/span>\nPath.of(<span class=\"hljs-string\">\"\/foo\/bar\/baz\"<\/span>);\nPath.of(<span class=\"hljs-string\">\"\/foo\"<\/span>, <span class=\"hljs-string\">\"bar\"<\/span>, <span class=\"hljs-string\">\"baz\"<\/span>);\nPath.of(<span class=\"hljs-string\">\"\/\"<\/span>, <span class=\"hljs-string\">\"foo\"<\/span>, <span class=\"hljs-string\">\"bar\"<\/span>, <span class=\"hljs-string\">\"baz\"<\/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>Als Parameter kannst du den gesamten Pfad oder Teile des Pfades angeben \u2013 in beliebigen Kombinationen, wie im Beispiel zu sehen.<\/p>\n\n\n\n<p>Um einen absoluten Pfad zu definieren, muss der erste Teil unter Linux und macOS mit \"\/\" beginnen und unter Windows mit einem Laufwerksbuchstaben, wie z. B. \"C:\".<\/p>\n\n\n\n<p><em>(F\u00fcr diese Erweiterung der Klassenbibliothek gibt es kein JDK Enhancement Proposal.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"epsilon-a-no-op-garbage-collector\">Epsilon: A No-Op Garbage Collector<\/h2>\n\n\n\n<p>Mit dem JDK 11 erhalten wir einen neuen Garbage Collector: den Epsilon GC.<\/p>\n\n\n\n<p>Der Epsilon GC macht ... nichts. Nun, nicht ganz. Er verwaltet die Allokation von Objekten auf dem Heap \u2013 er hat aber keinen Garbage-Collection-Prozess, mit dem er die Objekte wieder freigibt.<\/p>\n\n\n\n<p>Welchen Zweck hat ein Garbage Collector, der keinen Garbage collected?<\/p>\n\n\n\n<p>Folgende Einsatzszenarien sind denkbar:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Performance-Tests:<\/strong> Bei Micro-Benchmarks z. B., bei denen man verschiedene Implementierungen von Algorithmen miteinander vergleicht, ist ein regul\u00e4rer Garbage Collector hinderlich, da er die Ausf\u00fchrungszeiten beeinflussen und damit die Messergebnisse verf\u00e4lschen kann. Durch die Verwendung des Epsilon GC k\u00f6nnen solche Beeinflussungen ausgeschlossen werden.<\/li>\n\n\n\n<li><strong>Extrem kurzlebige Applikationen<\/strong>, wie z. B. f\u00fcr AWS Lambda entwickelte, sollen so schnell wie m\u00f6glich beendet werden. Ein Garbage-Collection-Zyklus w\u00e4re hier Zeitverschwendung, wenn die Applikation ohnehin wenige Millisekunden sp\u00e4ter wieder beendet wird.<\/li>\n\n\n\n<li><strong>Eliminierung von Latenzen:<\/strong> Wenn Entwicklerinnen und Entwickler den Speicherbedarf ihrer Anwendung gut kennen und komplett oder nahezu komplett auf Objekt-Allokationen verzichten, erm\u00f6glicht ihnen der Epsilon GC eine latenzfreie Anwendung zu implementieren.<\/li>\n<\/ul>\n\n\n\n<p>Epsilon GC wird \u2013 analog zu allen anderen Garbage Collectoren \u2013 \u00fcber folgende Option in der java-Befehlszeile aktiviert:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>-XX:+UseEpsilonGC<\/code><\/p>\n\n\n\n<p><em>(Epsilon GC ist definiert im&nbsp;<a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/318\" target=\"_blank\">JDK Enhancement Proposal 318<\/a>.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"launch-single-file-source-code-programs\">Launch Single-File Source-Code Programs<\/h2>\n\n\n\n<p>F\u00fcr kleine Java-Programme, die aus nur einer Klasse bestehen, wird der <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/330\" target=\"_blank\">JDK Enhancement Proposal 330<\/a> interessant.<\/p>\n\n\n\n<p>Damit ist es zum einen m\u00f6glich eine .java-Datei mit dem <code>java<\/code>-Kommando zu compilieren <em>und<\/em> auszuf\u00fchren. Zum anderen kann eine .java-Datei durch ein sogenanntes \"Shebang\" direkt ausf\u00fchrbar gemacht werden.<\/p>\n\n\n\n<p>Was genau das bedeutet, zeige ich dir an einem einfachen Beispiel.<\/p>\n\n\n\n<p>Erstelle dazu eine Datei mit dem Namen <code>Hello.java<\/code> und folgendem Inhalt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Hello<\/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    <span class=\"hljs-keyword\">if<\/span> (args.length &gt; <span class=\"hljs-number\">0<\/span>) {\n      System.out.printf(<span class=\"hljs-string\">\"Hello %s!%n\"<\/span>, args&#091;<span class=\"hljs-number\">0<\/span>]);\n    } <span class=\"hljs-keyword\">else<\/span> {\n      System.out.println(<span class=\"hljs-string\">\"Hello!\"<\/span>);\n    }\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Bisher musstest du dieses Programm zuerst mit <code>javac<\/code> compilieren, um es dann mit <code>java<\/code> ausf\u00fchren zu k\u00f6nnen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">$ javac Hello.java\n$ java Hello Anna\n\n\u27f6\n\nHello Anna!<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ab Java 11 kannst du den ersten Schritt weglassen:<\/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 Hello.java Anna\n\n\u27f6\n\nHello Anna!<\/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>Der Quellcode wird dabei in den Arbeitsspeicher compiliert und von dort ausgef\u00fchrt.<\/p>\n\n\n\n<p>Auf Linux und macOS kannst du noch einen Schritt weiter gehen und direkt ein ausf\u00fchrbares Java-Skript schreiben. Dazu musst du in der ersten Zeile ein sogenanntes \"Shebang\" und die Java-Version eintragen:<\/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\">#!\/usr\/bin\/java --source <span class=\"hljs-number\">11<\/span>\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Hello<\/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    <span class=\"hljs-keyword\">if<\/span> (args.length &gt; <span class=\"hljs-number\">0<\/span>) {\n      System.out.printf(<span class=\"hljs-string\">\"Hello %s!%n\"<\/span>, args&#091;<span class=\"hljs-number\">0<\/span>]);\n    } <span class=\"hljs-keyword\">else<\/span> {\n      System.out.println(<span class=\"hljs-string\">\"Hello!\"<\/span>);\n    }\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Die Datei darf keine .java-Endung haben. Benenne sie um in <code>Hello<\/code> und mache sie ausf\u00fchrbar:<\/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\">mv Hello.java Hello\nchmod +x Hello<\/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>Jetzt kannst du sie direkt ausf\u00fchren:<\/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\">$ .\/Hello Anna\n\n\u27f6\n\nHello Anna!<\/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>Ziemlich cool, oder? F\u00fcr kleinere Tools kann das sehr n\u00fctzlich sein.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"nest-based-access-control\">Nest-Based Access Control<\/h2>\n\n\n\n<p>Bei der Verwendung von inneren Klassen bekommen wir Java-Entwicklerinnen und -Entwickler immer wieder die folgende Warnung zu sehen:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_600\"><img decoding=\"async\" width=\"600\" height=\"350\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning-600x350.png\" alt=\"Synthetic-accessor-Warnung in IntelliJ\" class=\"wp-image-23468\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning-600x350.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning-224x131.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning-336x196.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning-504x294.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning-672x392.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning-400x233.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning-800x467.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning-944x551.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/Synthetic-accessor-warning.png 1200w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">Synthetic-accessor-Warnung in IntelliJ<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Was hat es damit auf sich?<\/p>\n\n\n\n<p>Die Java Language Specification (JLS) erlaubt den Zugriff auf private Felder und Methoden von inneren Klassen. Die Java Virtual Machine (JVM) hingegen erlaubt das (bisher) nicht.<\/p>\n\n\n\n<p>Um diesen Widerspruch aufzul\u00f6sen, f\u00fcgt der Java-Compiler (bis Java 10) beim Zugriff auf diese privaten Felder und Methoden sogenannte \"synthetische Accessor-Methoden\" ein \u2013 mit der Standard-Sichtbarkeit \"package-private\".<\/p>\n\n\n\n<p>Diese zus\u00e4tzlichen Methoden f\u00fchren dazu, dass scheinbar private Felder und Methoden vom gesamten Paket aus zug\u00e4nglich sind. Dementsprechend erfolgt die Warnung.<\/p>\n\n\n\n<p>Aufl\u00f6sen lie\u00df sich das bisher, indem man die entsprechenden Members entweder selbst package-private machte oder \u2013 dies ging nur in Eclipse \u2013 den Code mit der Annotation <code>@SuppressWarnings(\"synthetic-access\")<\/code> versah.<\/p>\n\n\n\n<p>Mit dem <a href=\"https:\/\/openjdk.org:443\/jeps\/181\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 181<\/a> wird die Zugriffskontrolle der JVM so erweitert, dass der Zugriff auf private Members von inneren Klassen ohne synthetische Accessor auskommt.<\/p>\n\n\n\n<p>Solltest du Methoden und Felder innerer Klassen aus o. g. Grund package-private gemacht haben oder <code>@SuppressWarnings<\/code> eingesetzt haben, dann kannst du das mit Java 11 wieder r\u00fcckg\u00e4ngig machen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"analyse-tools\">Analyse-Tools<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"java-flight-recorder\">Java Flight Recorder<\/h3>\n\n\n\n<p>Zahlreiche Tools helfen uns bei der Fehleranalyse und -behebung w\u00e4hrend des Entwicklungsprozesses. Bestimmte Probleme treten aber erst im Betrieb einer Anwendung auf. Deren Analyse ist oft schwer bis unm\u00f6glich, da wir solche Fehler oft nicht reproduzieren k\u00f6nnen.<\/p>\n\n\n\n<p>Java Flight Recorder (JFR) kann uns hier zur Seite stehen, indem er w\u00e4hrend des Betriebs einer Anwendung zahlreiche JVM-Daten aufzeichnet und in einer Datei zur nachtr\u00e4glichen Analyse bereitstellt.<\/p>\n\n\n\n<p>Flight Recorder existiert bereits seit mehrere Jahren als kommerzielles Feature im Oracle-JDK. Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/328\" target=\"_blank\">JDK Enhancement Proposal 328<\/a> wird er Teil des OpenJDK und kann damit frei eingesetzt werden.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Wie startet man Flight Recorder?<\/h4>\n\n\n\n<p>Du kannst Flight Recorder auf zwei Arten starten. Zum einen kannst du ihn beim Start einer Anwendung \u00fcber folgende Option in der java-Befehlszeile aktivieren:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>-XX:StartFlightRecording=filename=&lt;file name&gt;<\/code><\/p>\n\n\n\n<p>Zum anderen kannst du <code>jcmd<\/code> nutzen, um Flight Recorder in einer laufenden Java-Anwendung zu aktivieren:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>jcmd JFR.start filename=&lt;file name&gt;<\/code><\/p>\n\n\n\n<p>Bei beiden Varianten kannst du zahlreiche weitere Optionen angeben; z. B. kannst du mit \"duration\" festlegen, wie lange der Recorder laufen soll. Alle Optionen im Detail vorzustellen w\u00fcrde den Rahmen dieses Artikels sprengen. Du findest sie in der <a rel=\"noopener\" href=\"https:\/\/docs.oracle.com\/javacomponents\/jmc-5-4\/jfr-runtime-guide\/run.htm#JFRUH164\" target=\"_blank\">offiziellen Flight-Recorder-Dokumentation<\/a> von Oracle.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Java Flight Recorder Beispiel<\/h4>\n\n\n\n<p>In folgendem Beispiel sei 31100 die Prozess-ID der zu analysierenden Java-Anwendung. Die Aufzeichnung wird wie folgt gestartet (\u00fcber den optionalen Parameter \"name\" geben wir dabei einen Namen f\u00fcr die Aufzeichnung an):<\/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\">$ jcmd 31100 JFR.start filename=myrecording.jfr name=myrecording\n31100:\nStarted recording 1. No limit specified, using maxsize=250MB as default.\n\nUse jcmd 31100 JFR.dump name=myrecording to copy recording data to file.<\/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>In der Regel speichert Flight Recorder die Aufzeichnung nur in bestimmten Abst\u00e4nden und beim Beenden der Anwendung in die angegebene Datei. Du kannst die Aufzeichnung aber auch zwischendurch manuell speichern, indem du das Dump-Kommando ausf\u00fchrst, das dir beim Start angezeigt wurde:<\/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\">$ jcmd 31100 JFR.dump name=myrecording\n31100:\nDumped recording \"myrecording\", 344.8 kB written to:\n\n&lt;path&gt;\/myrecording.jfr<\/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>Falls du beim Start keinen \"name\"-Parameter angegeben hast, kannst du als Namen die Nummer der Aufzeichnung (im Beispiel oben \"1\") angeben.<\/p>\n\n\n\n<p>Stoppen kannst du Flight Recorder wie folgt:<\/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\">$ jcmd 31100 JFR.stop name=myrecording\n31100:\nStopped recording \"myrecording\".<\/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>Wie analysiert man nun die von Flight Recorder gespeicherte Datei?<\/p>\n\n\n\n<p>Dazu brauchen wir ein weiteres Tool...<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">JDK Mission Control<\/h4>\n\n\n\n<p>Zur Betrachtung der Analysedaten ben\u00f6tigst du ein weiteres Tool: JDK Mission Control. Auf der <a rel=\"noopener\" href=\"https:\/\/github.com\/openjdk\/jmc\" target=\"_blank\">GitHub-Seite des Projekts<\/a> findest du Links zu mehreren Distributoren, bei denen du Mission Control f\u00fcr Windows, Mac und Linux herunterladen kannst.<\/p>\n\n\n\n<p>\u00dcber \"File \/ Open File...\" l\u00e4dst du die Analysedatei. Mission Control zeigt dir zun\u00e4chst eine \u00dcbersicht der gesammelten Daten:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"554\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-800x554.png\" alt=\"JDK Mission Control - \u00dcbersicht\" class=\"wp-image-23531\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-800x554.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-224x155.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-336x233.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-504x349.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-672x465.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-400x277.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-600x416.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-944x654.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01-1200x831.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-01.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">JDK Mission Control - \u00dcbersicht<\/figcaption><\/figure>\n<\/div>\n\n\n<p>\u00dcber die Navigation links kannst du dann tiefer in bestimmte Bereiche, wie Threads, Speicherbelegung, Locks, etc... eintauchen. Unter \"Threads\" z. B. siehst du, welche Threads von wann bis wann liefen:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"554\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-800x554.png\" alt=\"JDK Mission Control - Threads\" class=\"wp-image-23532\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-800x554.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-224x155.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-336x233.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-504x349.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-672x465.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-400x277.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-600x416.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-944x654.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads-1200x831.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/JDK-Mission-Control-threads.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">JDK Mission Control - Threads<\/figcaption><\/figure>\n<\/div>\n\n\n<p>Auch unter den anderen Navigationspunkten findest du spannende Aufbereitungen der gesammelten Daten. Probier es am besten gleich selbst einmal aus!<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"low-overhead-heap-profiling\">Low-Overhead Heap Profiling<\/h3>\n\n\n\n<p>Ein wichtiges Werkzeug bei der Analyse von Speicherproblemen (z. B. hohe Gargabe-Collector-Zeiten oder OutOfMemoryErrors) sind Heap-Dumps zur Analyse der auf dem Heap liegenden Objekte. Der Markt bietet hierf\u00fcr zahlreiche Tools an. Was diese Werkzeuge bisher nicht verraten, ist, an welcher Stelle des Programmcodes die auf dem Heap liegenden Objekte erzeugt wurden.<\/p>\n\n\n\n<p>Mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/331\" target=\"_blank\">JEP 331<\/a> wird das Java Virtual Machine Tool Interface (JVMTI) \u2013 also das Interface, \u00fcber das diese Tools die Daten \u00fcber die laufende Anwendung beziehen \u2013 um die M\u00f6glichkeit erweitert, Stack Traces aller Objekt-Allokationen zu sammeln. Die Heap-Analyse Tools k\u00f6nnen diese Zusatzinformationen mit anzeigen und uns Entwicklern die Problemanalyse so wesentlich erleichtern.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"experimentelle-und-preview-features\">Experimentelle und Preview-Features<\/h2>\n\n\n\n<p>Auf experimentelle und Preview-Features werde ich nur kurz eingehen und stattdessen auf die Java-Versionen verweisen, in denen die Features als \"production-ready\" released werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"zgc-a-scalable-low-latency-garbage-collector-experimental\">ZGC: A Scalable Low-Latency Garbage Collector (Experimental)<\/h3>\n\n\n\n<p>Der \"Z Garbage Collector\" \u2013 kurz ZGC \u2013 ist ein von Oracle entwickelter alternativer Garbage Collector mit dem Ziel die Pausezeiten von Full GCs (also vollst\u00e4ndigen Collections \u00fcber alle Heap-Regionen) auf maximal 10 ms zu reduzieren \u2013 ohne dabei den Gesamtdurchsatz gegen\u00fcber dem G1GC um mehr als 15 % zu reduzieren.<\/p>\n\n\n\n<p>ZGC ist zun\u00e4chst nur f\u00fcr Linux verf\u00fcgbar. Aktivieren kannst du ihn mit den folgenden JVM-Flags:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>-XX:+UnlockExperimentalVMOptions -XX:+UseZGC<\/code><\/p>\n\n\n\n<p>ZGC wird in <a href=\"\/de\/java\/java-15-features\/#ZGC_A_Scalable_Low-Latency_Garbage_Collector\">Java 15<\/a> Produktionsstatus erreichen. Im entsprechenden Teil dieser Serie werde ich diesen neuen Garbage Collector detaillierter beschreiben.<\/p>\n\n\n\n<p><em>(Dieses experimentelle Release ist im <a href=\"https:\/\/openjdk.org:443\/jeps\/333\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 333<\/a> definiert.)<\/em><\/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>Dieser Abschnitt listet alle als \"deprecated\" markierten und aus dem JDK entfernten Features auf.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"remove-the-java-ee-and-corba-modules\">Remove the Java EE and CORBA Modules<\/h3>\n\n\n\n<p>Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/320\" target=\"_blank\">JDK Enhancement Proposal 320<\/a> werden folgende Module aus dem JDK entfernt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>java.xml.ws (JAX-WS)<\/li>\n\n\n\n<li>java.xml.bind (JAXB)<\/li>\n\n\n\n<li>java.activation (JAF)<\/li>\n\n\n\n<li>java.xml.ws.annotation (Common Annotations)<\/li>\n\n\n\n<li>java.corba (CORBA)<\/li>\n\n\n\n<li>java.transaction (JTA)<\/li>\n\n\n\n<li>java.se.ee (Aggregatormodul f\u00fcr die sechs zuvor genannten Module)<\/li>\n\n\n\n<li>jdk.xml.ws (Tools f\u00fcr JAX-WS)<\/li>\n\n\n\n<li>jdk.xml.bind (Tools f\u00fcr JAXB)<\/li>\n<\/ul>\n\n\n\n<p>Die genannten Technologien wurden urspr\u00fcnglich f\u00fcr die Java EE-Plattform entwickelt und wurden mit Java 6 in die Standard Edition \"Java SE\" integriert. In Java 9 wurden sie wieder als \"deprecated\" markiert und mit Java 11 endg\u00fcltig entfernt.<\/p>\n\n\n\n<p>Sollten dir diese Libraries beim Upgrade auf Java 11 fehlen, dann kannst du sie z. B. per Maven-Dependencies wieder in dein Projekt ziehen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"deprecate-the-nashorn-javascript-engine\">Deprecate the Nashorn JavaScript Engine<\/h3>\n\n\n\n<p>Die im JDK 8 eingef\u00fchrte JavaScript-Engine \"Nashorn\" wurde in Java 11 mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/335\" target=\"_blank\">JEP 335<\/a> als \"deprecated for removal\" markiert und soll in einer der zuk\u00fcnftigen Versionen vollst\u00e4ndig entfernt werden.<\/p>\n\n\n\n<p>Grund daf\u00fcr sind die rasanten Entwicklungsgeschwindigkeiten von ECMAScript (dem Standard hinter JavaScript) und der node.js-Engine, die eine Weiterentwicklung von Nashorn zu aufw\u00e4ndig gemacht haben.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"deprecate-the-pack200-tools-and-api\">Deprecate the Pack200 Tools and API<\/h3>\n\n\n\n<p>Pack200 ist ein in Java 5 eingef\u00fchrtes, spezielles Kompressionsverfahren, das insbesondere f\u00fcr .class- und .jar-Dateien h\u00f6here Kompressionsraten erreicht als Standardverfahren. Entwickelt wurde Pack200, um in den fr\u00fchen 2000ern m\u00f6glichst viel Bandbreite einzusparen.<\/p>\n\n\n\n<p>Der Algorithmus ist jedoch komplex, und die Weiterentwicklungskosten stehen in Zeiten von 100-MBit-Internetleitungen in keinem Verh\u00e4ltnis zum Nutzen mehr.<\/p>\n\n\n\n<p>Daher wurde das Tool mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/336\" target=\"_blank\">JDK Enhancement Proposal 336<\/a> als \"deprecated\" markiert und soll in einem der n\u00e4chsten Java-Releases entfernt werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"javafx-geht-eigene-wege\">JavaFX geht eigene Wege<\/h3>\n\n\n\n<p>Beginnend mit Java 11 wird JavaFX (und das dazugeh\u00f6rende Tool <code>javapackager<\/code>) nicht mehr mit dem JDK ausgeliefert. Du kannst es stattdessen als separates SDK von der <a rel=\"noopener\" href=\"https:\/\/openjfx.io\/\" target=\"_blank\">JavaFX-Homepage<\/a> herunterladen.<\/p>\n\n\n\n<p><em>(F\u00fcr diese \u00c4nderung gibt es kein JDK Enhancement Proposal.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sonstige-aenderungen-in-java-11-die-man-als-java-entwickler-nicht-unbedingt-kennen-muss\">Sonstige \u00c4nderungen in Java 11 (die man als Java-Entwickler nicht unbedingt kennen muss)<\/h2>\n\n\n\n<p>Dieser Abschnitt listet weitere \u00c4nderungen unter der Haube von Java 11 auf, von denen du wahrscheinlich nicht direkt etwas mitbekommen wirst. Es kann trotzdem sinnvoll sein, die folgenden Abschnitte einmal zu \u00fcberfliegen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"unicode-10\">Unicode 10<\/h3>\n\n\n\n<p>Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/327\" target=\"_blank\">JDK Enhancement Proposal 327<\/a> wurde Java 11 um Support f\u00fcr Unicode 10.0 erweitert.<\/p>\n\n\n\n<p>Was bedeutet das?<\/p>\n\n\n\n<p>Insbesondere die Klassen <code>String<\/code> und <code>Character<\/code> mussten um die neuen Codebl\u00f6cke und Zeichen erweitert werden. Relevant ist das z. B. f\u00fcr <code>String.toUpperCase()<\/code> und <code>toLowerCase()<\/code> sowie f\u00fcr <code>Character.getName()<\/code> und <code>Character.UnicodeBlock.of()<\/code>.<\/p>\n\n\n\n<p>Hier ist ein kurzes Code-Beispiel (der Unicode-Codepoint 0x1F929 steht f\u00fcr das Emoji \ud83e\udd29):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">System.out.println(<span class=\"hljs-string\">\"name  = \"<\/span> + Character.getName(<span class=\"hljs-number\">0x1F929<\/span>));\nSystem.out.println(<span class=\"hljs-string\">\"block = \"<\/span> + Character.UnicodeBlock.of(<span class=\"hljs-number\">0x1F929<\/span>));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Bis Java 10 gibt der Code 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\">name  = null\nblock = null<\/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>Java 11 hingegen kennt das neue Emoji \u2013 was f\u00fcr ein Gl\u00fcck ;-)<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">name  = GRINNING FACE WITH STAR EYES\nblock = SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><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 <code>String.toUpperCase()<\/code> und <code>toLowerCase()<\/code> kann ich hier kein sinnvolles Beispiel abdrucken, da die hinzugekommenen exotischen Schriften \"Masaram Gondi\", \"Nushu\", \"Soyombo\" und \"Zanabazar Square\" von kaum einem System dargestellt werden k\u00f6nnen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"improve-aarch64-intrinsics\">Improve Aarch64 Intrinsics<\/h3>\n\n\n\n<p>Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/315\" target=\"_blank\">JDK Enhancement Proposal 315<\/a> werden sogenannte \"Intrinsics\" f\u00fcr die AArch64-Plattform (also 64-Bit ARM-CPUs) verbessert und neue Intrinsics hinuzugef\u00fcgt.<\/p>\n\n\n\n<p>Intrinsics werden eingesetzt, um anstelle von Java-Code Architektur-spezifischen Assembler-Code auszuf\u00fchren, was die Performance bestimmter Methoden der JDK-Klassenbibliothek wesentlich verbessert.<\/p>\n\n\n\n<p>Mit diesem JEP werden Intrinsics f\u00fcr trigonometrische Funktionen und die Logarithmus-Funktion hinzugef\u00fcgt und bestehende Instrinsics f\u00fcr Methoden wie z. B. <code>String.compareTo()<\/code> und <code>String.indexOf()<\/code> optimiert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"transport-layer-security-tls-1-3\">Transport Layer Security (TLS) 1.3<\/h3>\n\n\n\n<p>Das JDK unterst\u00fctzte bisher die folgenden Sicherheitsprotokolle:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Secure Socket Layer (SSL) in der Version 3.0<\/li>\n\n\n\n<li>Transport Layer Security (TLS) in den Versionen 1.0, 1.1 und 1.2<\/li>\n\n\n\n<li>Datagram Transport Layer Security (DTLS) in den Versionen 1.0 und 1.2<\/li>\n<\/ul>\n\n\n\n<p>Mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/332\" target=\"_blank\">JEP 332<\/a> wurde diese Liste um den modernen Sicherheitsstandard TLS 1.3 erweitert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"chacha20-and-poly1305-cryptographic-algorithms\">ChaCha20 and Poly1305 Cryptographic Algorithms<\/h3>\n\n\n\n<p>Mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/329\" target=\"_blank\">JEP 329<\/a> wird das JDK um zwei Kryptografiealgorithmen \u2013 ChaCha20 und Poly1305 \u2013 erweitert. Diese werden z. B. von die im vorangegangenen Abschnitt genannten Sicherheitsprotokollen eingesetzt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"key-agreement-with-curve25519-and-curve448\">Key Agreement with Curve25519 and Curve448<\/h3>\n\n\n\n<p>Mit <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/324\" target=\"_blank\">JEP 324<\/a> werden die Schl\u00fcsselaustauschprotokolle des JDK um die sogenannten elliptischen Kurven \"Curve25519\" und \"Curve448\" erweitert. Beide Kurven erm\u00f6glichen eine besonders schnelle Ver- und Entschl\u00fcsselung des zu verwendenden symmetrischen Schl\u00fcssels.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"dynamic-class-file-constants\">Dynamic Class-File Constants<\/h3>\n\n\n\n<p>Das .class-Dateiformat wird um die Konstante <code>CONSTANT_Dynamic<\/code> erweitert, \"die Sprachentwicklern und Compiler-Implementierern breitere Optionen f\u00fcr Ausdrucksf\u00e4higkeit und Leistung bietet.\" Solltest du eine Sprache oder einen Compiler entwickeln wollen, findest du weitere Details im <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/309\" target=\"_blank\">JDK Enhancement Proposal 309<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vollstaendige-liste-aller-aenderungen-in-java-11\">Vollst\u00e4ndige Liste aller \u00c4nderungen in Java 11<\/h3>\n\n\n\n<p>Dieser Artikel hat alle Features von Java 11 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 <a href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/11-relnote-issues.html\" target=\"_blank\" rel=\"noopener\">offiziellen Java 11 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 Java 11 k\u00f6nnen wir \"var\" nun auch in Lambda-Parametern verwenden.<\/p>\n\n\n\n<p>Auf HTTP-Schnittstellen k\u00f6nnen wir komfortabel mit dem <code>HttpClient<\/code> zugreifen.<\/p>\n\n\n\n<p><code>String<\/code> wurde um einige hilfreiche Funktionen erweitert. Mit <code>Files.readString()<\/code> und <code>writeString()<\/code> k\u00f6nnen wir endlich ohne Drittbibliothek mit nur einer Zeile Code Textdateien lesen und schreiben, und mit <code>Path.of()<\/code> k\u00f6nnen wir <code>Path<\/code>-Objekte pr\u00e4gnanter erstellen als mit <code>Paths.get()<\/code>.<\/p>\n\n\n\n<p>Mit dem Epsilon Garbage Collector k\u00f6nnen wir Microbenchmarks ohne st\u00f6rende GC-Zyklen durchf\u00fchren.<\/p>\n\n\n\n<p>Kleine Programme, die aus nur einer Klasse bestehen, k\u00f6nnen wir mit einem Aufruf von <code>java<\/code> compilieren <em>und<\/em> ausf\u00fchren \u2013 oder sie mit einem \"Shebang\", wie wir es beispielsweise von Perl kennen, direkt ausf\u00fchrbar machen.<\/p>\n\n\n\n<p>Dank Nest-Based Access Control muss der Compiler keine synthetischen Zugriffsmethoden mehr einf\u00fcgen.<\/p>\n\n\n\n<p>Und mit dem Flight Recorder wurde ein sehr n\u00fctzliches Analyse-Tool, das bisher nur mit Supportvertrag von Oracle genutzt werden durfte, f\u00fcr alle frei verf\u00fcgbar gemacht. Ich kann nur empfehlen es einmal auszuprobieren!<\/p>\n\n\n\n<p>Wenn dir dieser \u00dcberblick gefallen hat, freue ich mich \u00fcber einen Kommentar oder wenn du den Artikel \u00fcber einen der Share-Buttons am Ende teilst. M\u00f6chtest du informiert werden, wenn der n\u00e4chste Artikel online geht? Dann <a href=\"#\" data-formkit-toggle=\"d8ee997126\">klicke hier<\/a>, um dich in meinen Mail-Verteiler einzutragen.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Alle neuen Features von Java 11: \"var\" in Lambdas, HttpClient, neue String- und Files-Methoden, Epsilon GC, Flight Recorder und mehr.<\/p>\n","protected":false},"author":1,"featured_media":34284,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"none","_seopress_titles_title":"","_seopress_titles_desc":"Alle neuen Features von Java 11 mit Beispielen: 'var' in Lambdas, HttpClient, neue String- und Files-Methoden, Epsilon GC, Flight Recorder und mehr.","_seopress_robots_index":"","_uag_custom_page_level_css":"","_wp_convertkit_post_meta":{"form":"-1","landing_page":"","tag":"0","restrict_content":"0"},"_metis_text_type":"standard","_metis_text_length":30239,"_post_count":0,"footnotes":""},"categories":[64],"tags":[176],"class_list":["post-23301","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-11-features.jpg",1770,986,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features.jpg",150,84,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features.jpg",768,428,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features.jpg",1024,570,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-224x125.jpg",224,125,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-504x281.jpg",504,281,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-672x374.jpg",672,374,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-400x223.jpg",400,223,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-600x334.jpg",600,334,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-800x446.jpg",800,446,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-944x526.jpg",944,526,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-1200x668.jpg",1200,668,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features-1770x735.jpg",1770,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-features.jpg",1536,856,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/java-11-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 11: \"var\" in Lambdas, HttpClient, neue String- und Files-Methoden, Epsilon GC, Flight Recorder und mehr.","public_identification_id":"3c78e136e89b4a36b1b837e6b360fdb1","private_identification_id":"b58d1d3089b04476babd941c7327e910","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/23301","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=23301"}],"version-history":[{"count":10,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/23301\/revisions"}],"predecessor-version":[{"id":39768,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/23301\/revisions\/39768"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/34284"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=23301"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=23301"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=23301"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}