References:
- "What's New in Oracle JDK 9" @ https://docs.oracle.com/javase/9/whatsnew/toc.htm.
- "JDK 9 release notes" @ https://www.oracle.com/technetwork/java/javase/9-relnotes-3622618.html.
- OpenJDK's JDK 9 @ https://openjdk.java.net/projects/jdk9/.
JDK 9 comes with these big new features (plus some minor new features and enhancements):
- Java Module System (Project Jigsaw)
- JDK 9 REPL (Read Evaluate Print Loop) -
jshell
- Some language changes, e.g., JEP 213: Milling Project Coin.
JDK 9 Java Module System - Project Jigsaw
See "Java Module System".
JDK 9 REPL - jshell
JDK 9 introduces a new tool called jshell
to support REPL (Read-Evaluate-Print-Loop). It is used to execute and test any Java constructs like class, interface, enum, object, statements etc. For example,
> jshell | Welcome to JShell -- Version 10.0.1 | For an introduction type: /help intro jshell> int i = 123 i ==> 123 jshell> i + 456 $2 ==> 579 jshell> System.out.println("hello") hello jshell> for (var i = 0; i < 3; ++i) ...> System.out.println(i*i) 0 1 4 jshell> /exit | Goodbye
JDK 9 New Language Features
Reference: Java Language Updates Java SE 9 @ https://docs.oracle.com/javase/9/language/toc.htm.
JDK 9 introduces a few new language features, under "JEP 213: Milling Project Coin".
private and private static methods in the interface
Prior to Java 8, an interface can have only two kinds of entities:
public
static
final
variables (constants)public
abstract
methods: method signature only without implementation.
You need to use an abstract
class if you have non-abstract
methods with implementations.
Java 8 introduces public
default
and public
static
methods into the interface. You could provide implementations in these methods.
JDK 9 supports private
methods and private
static
methods. In JDK 9, an interface can contains six kinds of entities:
public
static
final
variables (constant)public
abstract
methodspublic
default
methodspublic
static
methodsprivate
methods: meant for helper method accessible within the current interface only, so as to remove redundant codes. Not inherited by its subclasses and cannot be overridden.private
static
methods: class helper method accessible within the current interface only.
try-with-resources Improvements
Before Java 7, you need to use a try-catch-finally
construct to manage resource, and manually close all resource in the finally
. Java 7 introduces a new try
-with-resources construct which automatically closes all resources at the end of the statement. Read HERE.
If you already have a resource as a final
or "effectively final
" variable, you can use that variable in a try(resources)
clause without declaring a new variable. An "effectively final
" variable is one whose value is never changed after it is initialized. For example,
import java.io.FileReader; import java.io.FileWriter; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; // Copy from one file to another file line by line. // Java 7 has a try-with-resources statement, which ensures that // each resource opened in try(resources) is closed at the end of the statement. public class J9FileCopy { public static void main(String[] args) throws IOException { BufferedReader src = new BufferedReader(new FileReader("in.txt")); BufferedWriter dest = new BufferedWriter(new FileWriter("out.txt")); try (src; dest) { // This is permitted in JDK 9 String line; while ((line = src.readLine()) != null) { System.out.println(line); dest.write(line); dest.newLine(); } } catch (IOException ex) { ex.printStackTrace(); } // src and dest automatically close. // No need for finally to explicitly close the resources. } }
Before JDK 9, you need to create new variables:
...... try (BufferedReader src1 = src; BufferedWriter dest1 = dest) { ...... }
[TODO] Write a better example.
Other Minor Language Changes
@SafeVargs annotation is allowed on private instance methods
The @SafeVarargs
annotation can be applied only to methods that cannot be overridden. These include static
methods, final
instance methods, and, new in JDK 9, private
instance methods.
Allow the diamond operator with anonymous inner classes
In JDK 9, as long as the inferred type is denotable, you can use the diamond operator <>
when you create an anonymous inner class.
Removal of the underscore from the set of legal identifier names
If you use a single underscore character (_
) as an identifier, your source code can no longer be compiled.
JDK 9 Library Changes
Convenience Factory Methods for Collections (JEP 269)
Motivation
Prior to JDK 9, creating a small, unmodifiable collection of List
, Set
, or Map
involves constructing it, storing it in a local variable, and invoking add()
on it several times, and then wrapping it. For example,
Listlst1 = new ArrayList<>(); // construct and store in a local variable lst1.add("apple1"); // several add()'s lst1.add("orange1"); lst1.add("banana1"); lst1 = Collections.unmodifiableList(lst1); // wrap it
Alternatively, you could populate a collection using a "copy constructor" from another collection, for example,
Listlst2 = Collections.unmodifiableList( new ArrayList<>(Arrays.asList("apple2", "orange2", "banana2"))); // Using the "copy constructor" of ArrayList
Another alternative is to use the so-called "double brace" technique, which uses the instance-initializer construct in an anonymous inner class, for example,
Listlst3 = Collections.unmodifiableList(new ArrayList<>() {{ add("apple3"); add("orange3"); add("banana3"); }});
You could also use the Java 8's Stream API to construct small collections, by combining stream factory methods and collectors, for example,
Listlst4 = Collections.unmodifiableList( Stream.of("apple4", "orange4", "banana4").collect(Collectors.toList()));
JDK 9 New Features
JDK 9 provides a static
factory method called of()
in the List
, Set
, and Map
interfaces to simplify creation of unmodifiable instances of these collections. We can write:
List<String>lst = List.of("apple", "orange", "banana"); Set<String> set = Set.of("apple", "orange", "banana"); Map<Integer, String> map = Map.of(1, "apple", 2, "orange", 3, "banana");
For List
and Set
, the factory methods of()
are heavily overloaded for zero to ten elements, plus arbitrary number of elements, as follows:
// List interface's factory method to return an immutable list static <E> List<E> of(E... elements) // an arbitrary number of elements with varargs static <E> List<E> of() // zero elements static <E> List<E> of(E e1) // one element (fixed) static <E> List<E> of(E e1, E e2) // two elements static <E> List<E> of(E e1, E e2, E e3) // three elements ...... static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) // ten elements // Set interface has a similar set of overloaded methods
The of()
includes varargs overloads, so that there is no limit on the size. It is tuned for smaller sizes with fixed-argument overloads for up to ten of elements. While this introduces some clutter in the API, it avoids array allocation, initialization, and garbage collection overhead that is incurred by varargs calls.
For Map
, a set of fixed-argument methods are provided for zero to ten elements:
static <K,V> Map<K,V> of() // zero elements static <K,V> Map<K,V> of(K k1, V v1) // one element static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2) // two elements ...... static <K,V> Map<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) // ten elements
To support arbitrary number of elements, the Map
interface provides a static
method called ofEntries()
, which takes argument of Map.Entry
objects, as follows:
static <K,V> Map<K,V> ofEntries(Map.Entry<? extends K,? extends V>... entries)
Another static
method called entry()
is also provided to create a Map.Entry
object:
static <K,V> Map.Entry<K,V> entry(K k, V v) // Returns an immutable Map.Entry containing the given key and value.
For examples,
Map<Integer, String> m1 = Map.of(1, "apple1", 2, "orange2", 3, "banana3"); // three elements (fixed) Map<Integer, String> m2 = Map.ofEntries( // arbitrary elements Map.entry(1, "apple2"), Map.entry(2, "orange2"), Map.entry(3, "banana2"));
Note that interface's static
methods are not inherited, so it will not be possible to invoke them via an implementing subclasses, nor via an instance of the interface type.
Others
Process API Improvements
Added two new interfaces in Process API: java.lang.ProcessHandle
and java.lang.ProcessHandle.info
.
CompletableFuture API Improvements
Support delays and timeouts, add some utility methods and better sub-classing.
Reactive Streams
JDK 9 Reactive Streams API is a Publish/Subscribe Framework to implement asynchronous, scalable and parallel applications. JDK 9 introduces: java.util.concurrent.Flow
, java.util.concurrent.Flow.Publisher
, java.util.concurrent.Flow.Subscriber
, java.util.concurrent.Flow.Processor
.
Optional Class Improvements
JDK 9 added some useful new methods to java.util.Optional
class, such as stream()
.
Stream API Improvements
JDK 9 added four useful new default
methods to java.util.Stream
interface: dropWhile()
, takeWhile()
.
The takeWhile()
takes a predicate as an argument and returns a Stream
of subset of the given Stream
values until that predicate returns false for first time. If first value does NOT satisfy that predicate, it just returns an empty Stream
. For example,
Stream.of(1,2,3,4,5,6,7,8,9,10).takeWhile(i -> i < 5)
JDK 9 Other New Features
Enhanced @Deprecated annotation
Prior to JDK 9, @Deprecated
annotation is just a Marker interface without any methods. JDK 9 enhances @Deprecated
annotation to provide more information about deprecated API and also provide a tool jdeprscan
to analyze an application’s static usage of deprecated APIs. Two methods were added: forRemoval()
and since()
to serve this information.
HTTP2 Client
HTTP/2 is an improvement over HTTP/1.1:
- In HTTP/1.1, we cannot have more than six connections open at a time, so every request has to wait for the others to complete. HTTP/2 can send multiple requests for data in parallel over a single TCP connection, known as "HTTP/2 Multiplexing".
- In HTTP/1.1, every request sent to the server will have the header's additional data, which increases bandwidth. This can be eliminated in HTTP/2.0 by having headers packed into one compressed block that will be sent as a unit, known as "HTTP/2 Header Compression".
- In an HTTP/1.1, an HTML page is sent to the browser. The browser has to parse it and decide which assets are required, then request those assets from the server. This can be eliminated by "Server Push" in HTTP/2. It allows servers to push responses proactively to the client instead of waiting for the new request to process.
- Text is replaced by Binary in HTTP/2.
- Domain sharding and asset concatenation are no longer needed with HTTP/2.
JDK 9 introduces new HTTP2 Client API (under JEP 110: HTTP/2 Client (Incubator)). It supports both HTTP/1.1 and HTTP/2 protocols. It supports both synchronous (blocking mode) and asynchronous modes (using WebSocket API).
Multi-Resolution Image API
JDK 9 added an interface MultiResolutionImage
in java.awt.image
package, which encapsulates a set of images with different height and widths.
Miscellaneous
- GC (Garbage Collector) Improvements
- Stack-Walking API
- Filter Incoming Serialization Data
- Deprecate the Applet API (JEP 289: Deprecate the Applet API): The Applet API, which is rapidly becoming irrelevant as web-browser vendors remove support for Java browser plug-ins. JDK 9 marked
@Deprecated(since="9")
for applet classes, and removedappletviewer
tool. Developer should use alternative technologies such as Java Web Start or installable applications. - Indify String Concatenation
- Enhanced Method Handles
- Java Platform Logging API and Service
- Compact Strings
- Parser API for Nashorn
- Javadoc Search
- HTML5 Javadoc
REFERENCES & RESOURCES