Release von Java 10

Nach der Umstellung auf die sechsmonatigen Release-Zyklen ist nun kurz nach der Version 9 bereits Java 10 erschienen. Das mag verwunderlich erscheinen, da sich viele Entwickler noch gar nicht tiefer mit den Modularisierungsmöglichkeiten der letzten Version auseinandergesetzt haben und bisher kaum Anwendungen migriert wurden. Selbst viele Tool- und Frameworkhersteller sind im Moment noch dabei, überhaupt kompatible bzw. für Java 9 brauchbare Lösungen zu entwickeln. Von einer wirklichen Modularisierung sind die meisten ebenfalls noch weit entfernt.

Aber mit den neuen, kürzeren Releasezyklen wurde von Oracle auch der Long-Term-Support angepasst, nur noch jedes dritte Release wird eine langjährige Unterstützung bieten. Nach Java 8 wird dies erst wieder die Version 11 sein, die voraussichtlich im September 2018 erscheinen soll. Der Support für Java 9 ist bereits ausgelaufen und der für 10 läuft schon wieder in einem halben Jahr aus.

Aufgrund der Kürze der Zeit ist die Liste der Release Notes eher kurz. Viele Themen betreffen die Java Laufzeitumgebung, wie zum Beispiel:

  • Erweiterungen des G1, der jetzt die Full Garbage Collection parallelisieren kann
  • verringerter Memory Footprint durch das Teilen geladener Klassen zwischen Anwendungen
  • neuer, noch experimenteller Just-In-Time Compiler Graal
  • bessere Zusammenarbeit mit Docker Containern
  • neue Root-Zertifikate für das OpenJDK

An der JDK Klassenbibliothek gibt es laut den Release Notes auch nur minimale Änderungen, z. B. bei der Klasse Optional und in Form neuer Unmodifiable Collections und Stream Collector-Implementierungen (siehe dazu auch das Tool JDK-API-Diff). Die größte Änderung aus Entwicklersicht ist der Java Enhancement Process (JEP) 286 zur Local-Variable Type Inference. Wir kennen diesen Mechanismus in Java bereits bei Lambda-Parametern und beim Diamond-Operator für generische Datencontainer.

		// Type Inference bei Parametern von Lambda Ausdrücken (Java 8)
		Function<String, String> helloFunction = s -> "Hello " + s;
		
		// Inference von Generics (Diamond Operator, seit Java 7)
		List<String> strings = new ArrayList<>();
		strings.add(helloFunction.apply("World"));		

Mit dem Schlüsselwort var können jetzt sehr prägnant lokale Variablen definiert werden, deren Datentyp sich direkt aus der Zuweisung des Wertes ergibt. Während beim Diamond-Operator die Typinformation aus der linken Seite der Zuweisung geschlussfolgert wird, ist es bei Local Variable Type Inference genau andersherum.

        // int
        var zahl = 5;
        // String
        var string = "Hello World";
        // BigDecimal
        var objekt = BigDecimal.ONE;

Der Datentyp einer einmal deklarierten Variablen lässt sich natürlich nicht mehr ändern, sodass Zuweisungen inkompatibler Typen fehlschlagen.

        // Type wird bei Deklaration und Erstzuweisung vom Compiler festgelegt
        var zahl = 5;
        zahl = 7L; // incompatible types: possible lossy conversion from long to int

        var objekt = BigDecimal.ONE;
        objekt = BigInteger.TEN; // incompatible types: BigInteger cannot be converted to BigDecimal

Bei der Deklaration muss immer ein Wert zugewiesen werden, sonst kommt es zum Compiler-Fehler, auch wenn wie im folgenden Beispiel kurz darauf garantiert ein Wert zugewiesen werden würde.

        // Deklaration von "var" nur bei direkter Initialisierung der Variable
        var flag = true;
        var number; // Compiler-Fehler
        if (flag) {
            number = 5;
        } else {
            number = 7;
        }

Mit var deklarierte Variablen sind wie der Name schon verdeutlicht, nicht automatisch unveränderbar. Man kann sie aber mit dem Schlüsselwort final kombinieren. Außerdem sind sie effectively final (wenn es nur eine Zuweisung gibt) und können somit auch aus inneren Klassen und Lambda-Ausdrücken verwendet werden, ohne sie als final zu deklarieren.

        // Inference bei Neuzuweisung eines Wertes (var impliziert nicht "final")
        var zahl = 5;
        zahl = 7;

        // Inference auch mit "final" nutzbar, ansonsten gilt seit Java 8 ohnehin "effectively final Semantik"
        final var zahl = 5;

Die Typinferenz funktioniert auch mit generischen Typen und innerhalb der foreach-Schleife. Die Kombination mit dem Diamond-Operator führt aber aufgrund der fehlenden Typinformation zu einem Container von Object-Referenzen und somit zu weniger Typsicherheit.

            // Inference generischer Typen (List<String>)
            var strings = Arrays.asList("World", "Java 10");

            // Inference in Schleifen
            for (var string : strings) {
                System.out.println("Hello " + string);
            }

            // Kombination mit Diamond Operator führt zu Inferenz von List<Object>
            var strings = new ArrayList<>();
            strings.add("Hello World");
            for (var string : strings) {
                System.out.println(string.replace("World", "Java 10")); // cannot find symbol 'replace'
            }

            var strings2 = new ArrayList<String>();
            strings2.add("Hello World");
            for (var string : strings2) {
                System.out.println(string.replace("World", "Java 10"));
            }

Für Java 11 wird noch an einer Erweiterung der Local Variable Type Inference gearbeitet, die in Lambda-Ausdrücken funktioniert. Nützlich, wenn man Typinferenz mit Typ-Annotationen kombinieren möchte.

            // Ausblick Java 11 (JEP 323)
            // Inference von Lambda Parametern
            Consumer<String> printer = (var s) -> System.out.println(s); // statt s -> System.out.println(s);

            // aber keine Mischung von "var" und deklarierten Typen möglich
            // BiConsumer<String, String> printer = (var s1, String s2) -> System.out.println(s1 + " " + s2);

            // Nützlich für Type Annotations
            BiConsumer<String, String> printer = (@Nonnull var s1, @Nullable var s2) -> System.out.println(s1 + (s2 == null ? "" : " " + s2));

Java 10 kommt recht unaufgeregt daher, und die wenigsten werden es tatsächlich produktiv einsetzen. Aber gerade deshalb ist es schnell mal runtergeladen und ausprobiert. Die Arbeiten an Java 11 laufen bereits, der Erscheinungstermin wird der September 2018 sein.

Short URL for this post: https://wp.me/p4nxik-31o
This entry was posted in Java Basics and tagged , , , , . Bookmark the permalink.

One Response to Release von Java 10

  1. lolcio says:

    Sehr brauchbar informationen. Viel dank!

Leave a Reply