What are the changes in Java 13?

Hier gibt es diesen Artikel auf Deutsch

As the relase cycle of Java has changed we can now be excited for a new Java Release every half a year. So in September 2019 Java 13 will already come out. But don’t worry: Java developers do not need to be stressed: Today many years still use Java 8 *cough cough* uhm I mean Java 11 and the next LTS = Long Term Support-Version will be Java 17 in 2021.

So we will get two new versions of Java each year but at the same time they are mostly small releases with only a few additions. And some of the innovations are marked as preview, so you can still expect changes there after the community has been able to give feedback.

Enough talk, what are the new changes?

The following so called JPE’s = Java Enhancement Proposals are going to be relased with 13:

  • Switch Expressions (preview)
  • Text Blocks (preview)
  • Z Garbage Collector: Uncommit Unused Memory
  • Dynamic CDS Archives
  • Reimplementation of the Legacy Socket API

The first two points are especially interesting for developers. That’s why I wrote a whole chapter about those.

The ZGC = Z Gargabe Collector is a new… uhm, well a new Garbage Collector, as the name implies 🙂 It promises to clean big chunks of data on the heap very quickyl. Not only that but it will also free this space if it’s not being used anymore, something that apparently has not been done yet by the old garbage collector and some applications have used a lot of memory unnecessarily after a long time running.

Dynamics CDS Archives are an extension to the with Java 5 introduced CDS = Class Data Sharing. In CDS some specific information about application is stored in CDS archives to reduce the start time of applications. Until Java 10 only the Bootstrap Class Loader was able to use those archives. With Java 10 the AppCDS = Application Class Data Sharing has been published and now also other class loaders have access to those archives. To create those archives the application needed to be run in trial runs to figure out what classes could actually be loaded in an effective way. Now with Dynamics CDS these trial runs are not needed anymore.

And there is also a new implementation of the Socket API that still comes from JDK 1. NioSocketImplementation replaces the old PlainSocketImplementation. As the name suggests it’s derived from the New I/O-Implementation.
You can find more information for example here: https://docs.oracle.com/javase/8/docs/technotes/guides/io/index.html

How do I activate preview changes?

Preview means that there might still be changes in the future for those enhancements. To enable these preview features in Java 13 you need to add a flag to the compilation of your program:

javac --release 13 --enable-preview MyClass.java

You also need to add this flag when you start your application:

java --enable-preview MyClass

If you are using Maven you need to add the flag in the pom.xml to the maven-compiler-plugin part.

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>3.8.0</version>
	<configuration>
		<release>13</release>
		<compilerArgs>--enable-preview</compilerArgs>
	</configuration>
</plugin>

What are Switch Expressions?

Switch Expressions have the difference to the traditional Switch-Case statement so that you can directly return the values (and I actually mean the „return“ statement).

Note the new keyword yield instead of break.

Switch-Case example:

String name = "";
 switch(personalId) {
     case 1:
     case 2:
         name = "Fritz";
         break;
     case 3:
         name = "Hanswurst";
         break;
 };
 return name;

Example with Switch Expression:

return switch(personalId) {
     case 1, 2: yield "Fritz";
     case 3: yield "Hanswurst";
     default: yield "Defaultname";
 };

Since Java 12 you can also use the arrows to make the statement even simpler:

return switch(personalId) {
     case 1, 2 -> "Fritz";
     case 3 -> "Hanswurst";
     default -> "Defaultname";
 };

To be honest I myself barely use the Switch-Case statement. But from now on with the new Switch Expressions I will do everything in Switch statements, I promise!

What are Text Blocks?

Text Blocks simplify the usage of strings so that you can define a string in multiple lines without having these annoying + and „\n“ signs (for page break). For example you could do it to an SQL statement to make it more readable. This is already possible in various other programming languages like Groovy, Scala, Kotlin, C#, Swift or Python.

To create a Block simply use three quotation marks. Important: The opening quotation marks need to be in their own line!

So it was like this:

String meineSeite = "<html>n" + 
                    "<body>n" + 
	            "<p>Meine super Seite!</p>n" + 
		    "</body>n" + 
		    "</html>";

And now with text blocks – A wonderful new change! The world will never be the same! People will go out dancing in the streets! There will be festivals all dedicated to the Java god! So cherish this holy gift that we have received in the form of Text Blocks!

String meineSeite = """
                    <html> 
                      <body>
		        <p>Meine super Seite!</p>
		      </body>
		    </html>""";

Cool, right? 🙂

Welche Neuerungen gibt es in Java 13?

Click here to read this article in English

Dadurch, dass sich der Releasezyklus von Java geändert hat wird nun jedes halbe Jahr eine neue Java Version veröffentlicht. So erscheint im September 2019 Java 13. Java Entwickler müssen sich dadurch aber nicht stressen lassen: Immerhin verwenden immer noch viele Firmen Java 8 *hust hust* uhm ich meine Java 11 und die nächste LTS = Long Term Support-Version wird mit Java 17 im 2021 erscheinen.

Zwar kommen jetzt pro Jahr zwei Versionen auf den Markt, dafür sind sie meistens auch kleiner und überschaubarer. Dazu kommt, dass einige Änderungen erst einmal in einer Vorschau-Version herausgegeben wird, um das Feedback der Community einzuholen.

Genug geredet, was sind denn jetzt nun die Neuerungen?

Folgende sogenannte JPE’s = Java Enhancement Proposals werden in Java 13 erscheinen:

  • Switch Expressions (Vorschau)
  • Text Blocks (Vorschau)
  • Z Garbage Collector: Uncommit Unused Memory
  • Dynamic CDS Archives
  • Reimplementation of the Legacy Socket API

Für den Entwickler sind vorallem die ersten beiden Punkte interessant, weshalb ich diesen ein eigenes Kapitel widmen werde.

Bei ZGC = Z Gargabe Collector handelt es sich um eine neuen neuen… ähm, ja nun um einen Garbage Collector halt, wie der Name sagt 🙂 Dieser verspricht, auch bei Terabyte grossem Heap diesen schnell aufzuräumen und auch noch freizugeben. Das Freigeben war anscheinend bisher nicht der Fall, weshalb einige Anwendungen über eine längere Laufzeit mehr Speicher als nötig verwendet hatten.

Bei Dynamics CDS Archives handelt es sich um eine Erweiterung von den in Java 5 eingeführten CDS = Class Data Sharing. Bei diesem werden bestimte Informationen über Applikationen in CDS-Archiven abgelegt, um die Startzeit der Applikationen zu verkürzen. Dies war bis Java 10 aber dem Bootstrap Class Loader vorenthalten. Mit Java 10 wurde der AppCDS = Application Class Data Sharing eingeführt, mit dem auch andere Classloader auf diese Archive zugreifen können. Damit die CDS Archive angelegt werden konnten, mussten Probeläufe gemacht werden, um festzustellen, welche Klassen effektiv geladen werden sollten – Diese wurden dann in Klassenlisten gespeichert. Mit Dynamic CDS sollen nun diese Probeläufe wegfallen.

Und dann gibt es noch eine neue Implementation vom Socket API, welche noch aus dem JDK 1 stammen. NioSocketImplementation löst die veraltete PlainSocketImplementation. Der Name ist dabei abgeleitet der New I/O-Implementierung.
Mehr Infos dazu gibt es etwa unter https://docs.oracle.com/javase/8/docs/technotes/guides/io/index.html

Wie aktiviere ich Vorschau-Erweiterungen?

Vorschau bedeutet, dass es in Zukunft noch Änderungen an diesen Neuerungen geben kann. Damit diese dennoch mit Java 13 geladen werden, muss beim Kompilieren ein Flag mitgegeben werden:

javac --release 13 --enable-preview MyClass.java

Auch beim Starten der Applikation muss das Flag angegeben werden:

java --enable-preview MyClass

Wenn man Maven verwenden will, muss das Flag im pom.xml beim maven-compiler-plugin angegeben werden.

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>3.8.0</version>
	<configuration>
		<release>13</release>
		<compilerArgs>--enable-preview</compilerArgs>
	</configuration>
</plugin>

Was sind Switch Expressions?

Switch Expressions erlauben einem im Unterschied zu einem Switch-Case direkt Werte zurückzugeben (zurückgeben im Sinne von „return“).

Dabei muss das neue Schlüsselwort yield statt wie bisher break verwendet werden.

Switch-Case Beispiel:

String name = "";
 switch(personalId) {
     case 1:
     case 2:
         name = "Fritz";
         break;
     case 3:
         name = "Hanswurst";
         break;
 };
 return name;

Beispiel neu mit Switch Expression:

return switch(personalId) {
     case 1, 2: yield "Fritz";
     case 3: yield "Hanswurst";
     default: yield "Defaultname";
 };

Dabei kann man seit Java 12 auch die Pfeile verwenden, was noch simpler ist:

return switch(personalId) {
     case 1, 2 -> "Fritz";
     case 3 -> "Hanswurst";
     default -> "Defaultname";
 };

Ehrlich gesagt muss ich zugeben, dass ich selber praktisch nie Switch-Case verwende. Aber mit den neuen Switch Expressions werde ich alles nur noch mit Switch machen, versprochen!

Was sind Text Blocks?

Text Blöcke vereinfachen den Umgang mit Strings, indem man einfach einen ganzen Block über mehrere Zeilen angeben kann, ohne nervige + und „\n“ (für einen Zeilenumbruch) Zeichen. So können zum Beispiel SQL Statements lesbarer dargestellt werden. Dies ist in anderen Programmiersprachen wie Groovy, Scala, Kotlin, C#, Swift oder Python bereits möglich.

Zum Erstellen eines Text Block verwendet man dreifache Anführungszeichen. Wichtig dabei: Die öffnenden dreifachen Anführungszeichen müssen in einer eigenen Zeile stehen!

So war es bisher:

String meineSeite = "<html>\n" + 
                    "<body>\n" + 
	            "<p>Meine super Seite!</p>\n" + 
		    "</body>\n" + 
		    "</html>";

Und so ist es mit Text Blöcken – Eine wunderbare Veränderung! Die Welt wird nie mehr sein wie früher! Menschen werden frohlockend auf den Strassen tanzen! Es werden öffentliche Fester gehalten, um dem Java Gott zu huldigen! Darum seid dankbar für dieses heilige Geschenk der Text Blöcke!

String meineSeite = """
                    <html> 
                      <body>
		        <p>Meine super Seite!</p>
		      </body>
		    </html>""";

Cool, gell? 🙂

Wie erhalte ich das umgekehrte Resultat für einen Java Streams Filter?

Java Streams sind eine feine Sache. Ich habe das Gefühl, ich fange mittlerweile alle meine Java Beiträge mit diesem Satz an. 🙂

Ein Java Streams Filter erlaubt es einem, auf einfache Weise alle gewünschten Einträge aus einer Liste herauszufiltern und den Rest wegzuschmeissen. Alle roten Elefanten, alle Kinder unter 6 Jahren, alle Schlangen mit Flügeln und so weiter.

Oftmals ist es aber einfacher zu sagen, was man nicht will. Als quasi ‚Schau her, ich selektiere alle Kinder zwischen 5 und 8 Jahren… und jetzt, du superkluges Java, gib mir alle anderen Kinder!

Wie macht man das?

Not Predicate definieren

Ganz einfach: Wo auch immer man den Filter umgekehren will definiert man ein Not Predicate. Predicate ist ja dieses Dings in dem Filter, und wenn das „true“ ist, wird der jeweilige Eintrag behalten. Und mit einem Not Predicate drehen wir die Logik einfach um.

Folgenden Code irgendwo hinschmeissen:

public static <T> Predicate<T> not(Predicate<T> t) {
    return t.negate();
}

Und dann kann man das not im Filter verwenden.

Beispiel: Ihr habt eine Liste mit Kindernamen und findet den Namen „Rupert“ einfach wiederlich, den wollt Ihr unbedingt losweren. Also definieren wir zuerst einen Filter für den Namen ‚Rupert‘:

Arrays.stream(kindernamen).filter(kindername -> kindername.contains("Rupert")).collect(Collectors.toList());

Dieser Filter würde jetzt also alle Ruperts in der Resultateliste haben.

Dann kehren wir den Filter einfach um:

Arrays.stream(kindernamen).filter(not(kindername -> kindername.contains("Rupert"))).collect(Collectors.toList());

Et voilà.

Java 11 hats schon drin

Kleine Randbemerkung: In Java 11 ist genau diese Methode beim Predicate schon dabei:

Predicate.not( … )

Siehe https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/function/Predicate.html#not(java.util.function.Predicate)

Dann geht unser Rupert-Hass-Filter folgendermassen (und das Predicate muss man natürlich nicht mehr selber definieren):

Arrays.stream(kindernamen).filter(Predicate.not(kindername -> kindername.contains("Rupert"))).collect(Collectors.toList());