Least significant bits of Java 9
Prologue
Although the flagship feature of Java 9 is Modularity, a large number of other enhancements are planned for this release. This article will provide an overview of those features that are scheduled for Java 9 release but are not as famous and glorious as the Jigsaw.
Reactive Streams
Reactive Streams is a contract for asynchronous stream processing with non-blocking back pressure. Publisher
and Subscriber
are two key concepts in the Reactive Streams specification. Publisher
is a producer of items (and related control messages) that will be received by Subscriber
s, all these are done in a non-blocking way. Back pressure allows to control the amount of inflight data. That is, it will regulate the transfer between a slow publisher and a fast consumer and a fast publisher and a slow consumer.
Reactive Streams specification is comprised of four interfaces: Publisher
, Subscriber
, Subscription
and Processor
.
Publisher
is a producer of items which Subscriber
s can subscribe to. Subscriber
provides four callbacks: onNext
will be called every time a new item is available. There are also two terminal signals, onComplete
to signal the successful completion of the subscription and onError
to signal an unrecoverable error encountered by a Publisher
or Subscription
. Subscription
encapsulates the communication between Publisher
and Subscriber
: one can request zero or more elements from the publisher or even cancel the subscription altogether. Processor
is a component that acts as both a Subscriber
and Publisher
.
Reactive Streams will be integrated in Java 9. In java.util.concurrent
there is a Flow
class that contain these four interfaces. Note that these are just the interfaces, Java 9 (or possibly any version of Java) won’t be shipped with an implementation for this specification. So in order to actually use a reactive API, at some point you should use an implementation. Current notable implementations of this specification on the JVM are Project Reactor (which will be integrated in Spring 5), Akka Streams and RxJava.
More Concurrency Updates
Suppose we have a CompletableFuture
that going to fetch some movie recommendations from our fictional recommendation service. Now we want to add the capability of loading some static recommendations if the service couldn’t provide the expected result in a timely manner:
Here if the recommendation service could provide the recommendations in less than 1 second, we’ll show those recommendations to the end user. Otherwise, we’ll make the poor user to watch Fight Club one more time. The new completeOnTimeout(T value, long timeout, TimeUnit unit)
method completes the CompletableFuture
with the given value if it’s not completed before the given timeout.
If you don’t want to provide the static recommendation, you can simply raise a TimeoutException
with the orTimeout(long timeout, TimeUnit unit)
method:
Java 9 also will be shipped with some other enhancements to the CompletableFuture
API, which was introduced in Java 8. There was a completedFuture
static factory method in Java 8 to create a new CompletableFuture
that is already completed with the given value. If you want to create an already failed CompletableFuture
, you can use the new failedFuture
static factory method:
Also there will be completedStage
and failedStage
methods which will create new CompletionStage
s that is already completed or failed, respectively.
Convenience Factory Methods for Collections
The goal of JEP 269 is to:
Define library APIs to make it convenient to create instances of collections and maps with small numbers of elements, so as to ease the pain of not having collection literals in the Java programming language.
For example, in order to create a List
with few String
s in it:
Or to create a Map
from singer name to his/her band name:
Same code can be refactored as:
The Java Shell
Java Shell or JShell is the Read Eval Print Loop (REPL) environment for Java. That is, an interactive tool to evaluate declarations, statements, and expressions of the Java programming language. To start experimenting with JShell, open up a terminal and just type jshell
(assuming jshell
is accessible from your PATH
):
JShell is an interactive Java shell that accepts your Java code snippets and evaluates them in real time and tells you the result. So there is no need to create a public static void main
to test an API, anymore!
For starters, let’s declare a variable:
As you can see semicolons are optional. JShell supports Tab completion, just type a few chars and hit Tab and JShell tries its best to complete that name:
When you did choose a method name, you can hit the Shift and Tab to see all overloaded versions of the chosen method:
Hit it one more time to see the Javadoc:
If you evaluate an expression and don’t assign it to a variable, it will be assigned to a Pseudo Variable, which starts with $
:
Here the $3
pseudo variable will hold the foo
value, you can make sure of that fact by:
Here’s a List
of three programming languages:
Now we’re gonna just keep those languages that their name starts with the letter J
:
Here JShell couldn’t find the Collectors
symbol. By default JShell provides a set of common imports:
Since Collectors
isn’t part of those default imports, we should bring it to the scope:
Anyway, JShell is all about exploratory programming with features to ease interaction, including: a history with editing, tab-completion, automatic addition of needed terminal semicolons, and configurable predefined imports and definitions.
New IO Features
Probably the most familiar code snippet for every single Java developer is the following:
In Java 9 there is a readAllBytes
method for InputStream
which reads all remaining bytes from the input stream and
returns a byte array containing the bytes read from that input stream. Finally After 20 years we can simply write:
There is also a readNBytes(byte[] b, int off, int len)
method which reads the requested number of bytes from the input stream into the given
byte array.
Do you ever want an easy way to write contents of a Java InputStream
to an OutputStream
? The newly added transferTo(OutputStream out)
method will read all bytes from the input stream and writes the bytes to the given output stream in the order that they are read. So in order to write contents of a Java InputStream
to an OutputStream
, one can:
New HTTP Client
The new HTTP Client will be shipped with Java 9 but as part of an Incubator module named jdk.incubator.httpclient. Incubator modules are a means of putting non-final APIs in the hands of developers while the APIs progress towards either finalization or removal in a future release.
The other new addition to Java 9 is the new HTTP client API which supports HTTP/2 and WebSocket. This client isn’t in the java.base
module, so we should declare a dependency to the jdk.incubator.httpclient
module in our module-info.java
:
There is a HttpRequest
to represent an HTTP request which can be sent to a server:
By calling the response()
method you can send the request and block until a response comes from the server encapsulated as a HttpResponse
:
For more details on this new API, you can checkout the Java 9: High level HTTP and WebSocket API post.
And More!
Stream
and Optional
, which first were introduced in Java 8, hasn’t undergone any significant changes but there will be some new and useful methods there. Stream
would have dropWhile
and takeWhile
methods to drop or take only elements that match the given Predicate
. New stream()
method in Optional
can be used to convert the Optional
to a Stream
of at most one element. Also, ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
method is useful for scenarios when you want to consume the optional value if it’s present or supply a empty action if it’s not.
LocalDate
will have a datesUntil(LocalDate endExclusive)
method which returns a sequential ordered stream of dates, starting from this date and goes to endExclusive
(exclusive) by an incremental step of 1 day. For example, in order to count number of leap years between my birthday and current date:
For this particular scenario, using a 1 year step is more plausible (instead of default 1 day):
Sometimes in Java we had to write statements like:
languages like groovy are providing an Elvis operator which is a shortening of the ternary operator:
Java doesn’t provide such a syntactic sugar but Objects
utility class will have requireNonNullElse
and requireNonNullElseGet
methods to kinda (not as smooth and cool as Elvis operator) alleviates that problem: