Java 10 and later New Features

Content:

  1. Version numbers
  2. Version 10 (18.3)
    1. Release
    2. Collections
    3. var declaration
    4. Other
  3. Version 11 (18.9 LTS)
    1. Release
    2. Removed
    3. New HTTP client
    4. Other
    5. Support
  4. Version 12
    1. Release
    2. New switch
    3. Other
  5. Version 13
    1. Release
    2. New switch
    3. Text blocks
    4. Other

Version numbers:

Java version Official name Code name Release date
1.0 JDK 1.0 January 23rd 1996
1.1 JDK 1.1 February 19th 1997
1.2 J2SE 1.2 Playground December 8th 1998
1.3 J2SE 1.3 Kestrel May 8th 2000
1.4 J2SE 1.4 Merlin February 6th 2002
1.5/5 Java SE 5 Tiger September 30th 2004
1.6/6 Java SE 6 Mustang December 11th 2006
1.7/7 Java SE 7 Dolphin July 7th 2011
1.8/8 Java SE 8 March 18th 2014
1.9/9 Java SE 9 September 21st 2017
10/18.3 Java SE 10 March 20 2018
11/18.9 LTS Java SE 11 September 25th 2018
12 Java SE 12 March 19th 2019
13 Java SE 13 September 17th 2019

Version 10 (18.3):

Release:

Java 10 was released March 20 2018.

It is the first release with the new release cycle and policy.

It is not a LTS release.

Collections:

Java 10 has some new ways to create unmodifiable copies of collections.

List/Map/Set got a copyOf method.

Collectors got toUmodifiableList/toUmodifiableMap/toUmodifiableSet.

Java 9 examples:

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Copy9 {
    public static void main(String[] args) {
        List<String> lst = List.of("A", "BB", "CCC");
        List<String> lst2 = Collections.unmodifiableList(new ArrayList<String>(lst));
        for(String s : lst2) {
            System.out.println(s);
        }
        Map<Integer,String> mp = Map.of(1, "A", 2, "BB", 3, "CCC");
        Map<Integer,String> mp2 = Collections.unmodifiableMap(new HashMap<Integer,String>(mp));
        System.out.println(mp2.get(2));
    }
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class StreamCopy9 {
    public static void main(String[] args) {
        List<String> lst = List.of("A", "BB", "CCC");
        List<String> lst2 = Collections.unmodifiableList(lst.stream().collect(Collectors.toList()));
        for(String s : lst2) {
            System.out.println(s);
        }
        Map<Integer,String> mp = Map.of(1, "A", 2, "BB", 3, "CCC");
        Map<Integer,String> mp2 = Collections.unmodifiableMap(mp.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())));
        System.out.println(mp2.get(2));
    }
}

Java 10 examples:

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Copy10 {
    public static void main(String[] args) {
        List<String> lst = List.of("A", "BB", "CCC");
        List<String> lst2 = List.copyOf(lst);
        for(String s : lst2) {
            System.out.println(s);
        }
        Map<Integer,String> mp = Map.of(1, "A", 2, "BB", 3, "CCC");
        Map<Integer,String> mp2 = Map.copyOf(mp);
        System.out.println(mp2.get(2));
    }
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class StreamCopy10 {
    public static void main(String[] args) {
        List<String> lst = List.of("A", "BB", "CCC");
        List<String> lst2 = lst.stream().collect(Collectors.toUnmodifiableList());
        for(String s : lst2) {
            System.out.println(s);
        }
        Map<Integer,String> mp = Map.of(1, "A", 2, "BB", 3, "CCC");
        Map<Integer,String> mp2 = mp.entrySet().stream().collect(Collectors.toUnmodifiableMap(e -> e.getKey(), e -> e.getValue()));
        System.out.println(mp2.get(2));
    }
}

OK feature but I do not think it is important.

var declaration:

Java 10 adds var declartion aka type inference similar to the one C# got in version 3 and as present in many newer JVM languages as well.

Example with traditional declarations:

public class Var9 {
    public static void main(String[] args) {
        int i1 = 123;
        int i2 = 456;
        System.out.println(i1 + i2);
        String s1 = "ABC";
        String s2 = "DEF";
        System.out.println(s1 + s2);
    }
}

Example with var declarations:

public class Var10 {
    public static void main(String[] args) {
        var i1 = 123;
        var i2 = 456;
        System.out.println(i1 + i2);
        var s1 = "ABC";
        var s2 = "DEF";
        System.out.println(s1 + s2);
    }
}

Note that this is exactly as type safe as before. The variable do get the same type as before and the exact same treatment. The only change is that the developer do not need to write the type name.

To prevent too much compatibility issues then var is implemented as a pseudo type or a context specific keyword, which means that variables being named var in existing code will continue to work.

It can be a nice feature. And I am sure that this feature will be used a lot. In fact I suspect that it will be misused. Overusing such a feature can actually reduce readability of code in my opinion, so it should only be used when the actual type is easy to deduce for humans.

Other:

javah utility is removed and instead the javac -h option introduced in Java 8 has to be used.

A new experimental JIT compiler has been added. It get activated by using:

java -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler ...

So far the the new JIT compiler does seeem to be faster than the traditional - in fact it seems sligtly slower. But that may change as it matures.

Version 11 (18.9 LTS):

Release:

Java 11 was released September 25th 2018.

It is the first LTS release with the new release cycle and policy.

Please read the license note on Oracle download page carefully. Oracle JDK is now only available under commercial terms (free for development, cost money for production). For free version for any usage (both development and production) the option is Oracle OpenJDK.

OpenJDK is available from jdk.java.net.

Removed:

Java 11 is actually more about old features being removed than about new features being added.

Features removed:

I am sorry to see the web service client stuff go away. Yes - it is easy to get from the net (Apache Axis 2.x, Apache CXF or Metro). But I still think it is nice to have with Java SE.

CORBA support has been irrelevant for 15+ years and JTA is very much Java EE, so I don't see a problem with them being removed from Java SE.

I am sorry that JavaFX no longer being distributed with Java SE. JavaFX is actually a pretty nice GUI framework. See more here.

Metro kit with JAX-WS including wsimport utility can be downloaded from here.

Reference implementation of JAXB can be downloaded from here.

OpenJFX (JavaFX for Java 11+) can be downloaded here.

New HTTP client:

Java 11 got the new HTTP client that was introduced in uncubator mode in Java 9 (read more here).

Traditional Java code:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;

public class HttpTrad {
    public static void testGET() throws IOException {
        URL url = new URL("http://localhost:81/test.txt");
        URLConnection con = url.openConnection();
        con.connect();
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String line;
        while((line = br.readLine()) != null) {
            System.out.println(line);
        }
        br.close();
    }
    public static void testPOST() throws IOException {
        URL url = new URL("http://localhost:81/test.php");
        URLConnection con = url.openConnection();
        con.setDoOutput(true);
        con.connect();
        PrintWriter pw = new PrintWriter(con.getOutputStream());
        pw.println("f=123");
        pw.close();
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String line;
        while((line = br.readLine()) != null) {
            System.out.println(line);
        }
        br.close();
    }
    public static void main(String[] args) throws IOException {
        testGET();
        testPOST();
    }
}

This code is not that long, but it is not very clear what it is doing.

Apache HttpClient code:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;

public class HttpApache {
    public static void testGET() throws IOException {
        HttpClient client = HttpClientBuilder.create().build();
        HttpGet request = new HttpGet("http://localhost:81/test.txt"); 
        HttpResponse response = client.execute(request);
        BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        String line;
        while((line = br.readLine()) != null) {
            System.out.println(line);
        }
        br.close();
    }
    public static void testPOST() throws IOException {
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost request = new HttpPost("http://localhost:81/test.php"); 
        request.setEntity(new StringEntity("f=123", ContentType.APPLICATION_FORM_URLENCODED));
        HttpResponse response = client.execute(request);
        BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        String line;
        while((line = br.readLine()) != null) {
            System.out.println(line);
        }
        br.close();
    }
    public static void main(String[] args) throws IOException {
        testGET();
        testPOST();
    }
}

This code is much clearer.

New Java 11 code:

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest.BodyPublishers;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.stream.Stream;

public class Http11 {
    public static void testGET() throws IOException, InterruptedException {
        HttpClient client = HttpClient.newBuilder().build();
        HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:81/test.txt")).GET().build();
        HttpResponse<Styream<String>> response = client.send(request, BodyHandlers.ofLines());
        response.body().forEach(line -> System.out.println(line));
    }
    public static void testPOST() throws IOException, InterruptedException {
        HttpClient client = HttpClient.newBuilder().build();
        HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:81/test.php")).POST(BodyPublishers.ofString("f=123")).header("Content-Type", "application/x-www-form-urlencoded").build();
        HttpResponse<Styream<String>> response = client.send(request, BodyHandlers.ofLines());
        response.body().forEach(line -> System.out.println(line));
    }
    public static void main(String[] args) throws IOException, InterruptedException {
        testGET();
        testPOST();
    }
}

This code is short and concise. At least if one likes fluent style.

Other:

There are a few minor new features:

Support:

The support (patch availability) situation for Java is changing.

Java Support in the past Support going forward
Free Oracle Java Some years N/A
(take OpenJDK)
Free OpenJDK Some years Non-LTS: 6 months
LTS: 6 months / 4 years
OpenJDK project itself will supposedly not offer long term support
but AdoptOpenJDK will - see https://adoptopenjdk.net/support.html
Azul Zulu (OpenJDK with support) Many years Non-MTS/LTS: 6 months
MTS: 3 years
LTS: 8 years
see https://www.azul.com/products/zulu-and-zulu-enterprise/zulu-enterprise-java-support-options/
Commercial Oracle Java Many years Non-LTS: 6 months
LTS: 5 years/8 years/indefinite
see http://www.oracle.com/technetwork/java/javase/eol-135779.html
Other commercial vendors See their official EOL policy
(typical many years)
See their official EOL policy
(probably still many years for LTS versions)

Please check carefully yourself. The above is my best understanding at the time of writing, but I can have misunderstood what I read or the support policy can have been changed since then.

Version 12:

Release:

Java 12 was released March 19th 2019.

The free OpenJDK version is available here.

In my opinion Java 12 is a very small update.

New switch:

Java 12 introduces a new switch statement that seems inspired by Kotlin.

Traditional switch:

public class S11 {
    public enum Suits { CLUBS, SPADES, HEARTS, DIAMONDS }
    public static void test1(Suits s) {
        switch(s) {
            case CLUBS:
            case SPADES:
                System.out.println("Black");
                break;
            case HEARTS:
            case DIAMONDS:
                System.out.println("Red");
                break;
        }
    }
    public static void test2(Suits s) {
        int val = 0;
        switch(s) {
            case CLUBS:
                val = 1;
                break;
            case SPADES:
                val = 4;
                break;
            case HEARTS:
                val = 3;
                break;
            case DIAMONDS:
                val = 2;
                break;
        }
        System.out.println(val);
    }
    public static void main(String[] args) {
        test1(Suits.SPADES);
        test2(Suits.SPADES);
    }
}

New switch:

public class S12 {
    public enum Suits { CLUBS, SPADES, HEARTS, DIAMONDS }
    public static void test1(Suits s) {
        switch(s) {
            case CLUBS, SPADES -> System.out.println("Black");
            case HEARTS, DIAMONDS -> System.out.println("Red");
        }
    }
    public static void test2(Suits s) {
        int val = switch(s) {
            case CLUBS -> 1;
            case SPADES -> 4;
            case HEARTS -> 3;
            case DIAMONDS -> 2;
        };
        System.out.println(val);
    }
    public static void main(String[] args) {
        test1(Suits.SPADES);
        test2(Suits.SPADES);
    }
}

I think it is a nice feature, but it will not revolutionize the world.

Other:

There are also some changes to garbage collection.

Version 13:

Release:

Java 13 was released Septmber 17th 2019.

The free OpenJDK version is available here.

In my opinion Java 13 is a very small update.

New switch:

Java 13 enhances the new switch introduced in Java 12.

Switch expression in Java 12 does not work with multiple statements:

public class SE12 {
    public enum Suits { CLUBS, SPADES, HEARTS, DIAMONDS }
    public static void test(Suits s) {
        int val = 0;
        switch(s) {
            case CLUBS:
                System.out.println("Black");
                val = 1;
                break;
            case SPADES:
                System.out.println("Black");
                val = 4;
                break;
            case HEARTS:
                System.out.println("Red");
                val = 3;
                break;
            case DIAMONDS:
                System.out.println("Red");
                val = 2;
                break;
        }
        System.out.println(val);
    }
    public static void main(String[] args) {
        test(Suits.SPADES);
    }
}

Java 13 adds yield keyword to support that:

public class SE13 {
    public enum Suits { CLUBS, SPADES, HEARTS, DIAMONDS }
    public static void test(Suits s) {
        int val = switch(s) {
            case CLUBS:
                System.out.println("Black");
                yield 1;
            case SPADES:
                System.out.println("Black");
                yield 4;
            case HEARTS:
                System.out.println("Red");
                yield 3;
            case DIAMONDS:
                System.out.println("Red");
                yield 2;
        };
        System.out.println(val);
    }
    public static void main(String[] args) {
        test(Suits.SPADES);
    }
}

This is preview only so one has to use:

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

to use this feature.

I think it is an OK feature, but not important.

Text blocks:

Java 13 add a syntax for multiline strings.

Traditionally one has had to explicit put line breaks in form of escape sequence into the string to get multiline:

public class TB12 {
    public static void main(String[] args) {
        String s = "A\r\n" +
                   "BB\r\n" +
                   "CCC\r\n";
        System.out.println(s);
    }
}

In Java 13 that can be done using triple quotes:

public class TB13 {
    public static void main(String[] args) {
        String s = """
A
BB
CCC
                   """;
        System.out.println(s);
    }
}

This is preview only so one has to use:

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

to use this feature.

I think it is a nice feature.

Other:

There are also some changes to socket implementation.

Article history:

Version Date Description
1.0 March 4th 2018 Initial version
1.1 August 14th 2018 Update with Java 11 information
1.2 October 1st 2018 Update with Java 11 release info and license note
1.3 February 25th 2019 Update with Java 12 information
1.4 March 23rd 2019 Update with Java 12 release info
1.5 October 5th 2019 Update with Java 13 information

Other articles:

See list of all articles here

Comments:

Please send comments to Arne Vajhøj