Java 9
Java is a programming language and computing platform first released in 1995. Since then Java had gone through many changes and improvements until it reached its current version (version 13). Currently, Java is a fast, secure, and reliable programming language, used in data-centers, game consoles, cell phones to even scientific researched with supercomputers. Java is literally everywhere!
In this article, we will be looking at Java 9 release (2017) and the main new features and improvements since java 8 release (2014). It won’t include everything, but the ones which are more common or have more uses from my opinion.
Modularity & Jigsaw
A major concern for software developers is designing big complex projects. When a project has tens of thousands of lines of code or even more, it becomes increasingly harder to have knowledge and understanding of code segments. To overcome the problem of repeating and mixing-up similar code in different stages of programming, modularity was designed and used. Modularity encourages the idea of separating code into distinct and independent segments that perform a specific functionality. These segments can be referenced from any part of the project. Similar segments and functions are grouped together and called modules.
Modules were introduced in java 9 for the first time. Prior to Java 9, classes resided in packages and classes within those packages were found by class loaders. Now, modules act in-between packages and class loaders. The resources and packages can be encapsulated from other modules in levels that were just not possible before.
So now, it is impossible to use classes from other modules unless it was public class and explicitly exported from the module. For older projects, developers can use unnamed modules for backward compatibility.
Jigsaw project
Project Jigsaw is the umbrella project for modularity in java. Using Jigsaw, we can create a modular based project and define relation between the modules, which will make the construction and maintaining of libraries easier. In addition, it will improve the applications performance and security.
The module system supports the top level construct, just like packages. Developers can declare dependencies between modules after creating the modules, the definition will be added to the module’s info file (module-info.java).
A general Jigsaw project’s structure of the modules looks like:
src
|----com.test.greetings
| |----module-info.java
| |----com
| |----greetings
| |----GreetingsWorld.java
|----com.test.hello
|----module-info.java
|----com
|----hello
|----HelloWorldImpl.java
|----HelloWorldInterface.java
Module usage and Terminologies
With the introduction of modularity, new terminologies were added as well.
- module: the module definition file starts with this keyword followed by its name and definition.
module com.greetings{
}
- requires: used to indicate the modules it depends on; a module name has to be specified after this keyword.
module com.greetings{
requires com.hello;
}
- requires static: used when the dependency is option, it will make the dependency compile-time-only dependency.
module com.greetings{
requires static com.hello;
}
- requires transitive: any module depends on the module defining requires transitive
gets an implicit dependence on the .
module com.greetings{
requires transitive com.hello;
}
- exports: is used to indicate the packages within the module available publicly, a package name has to be specified after this keyword.
module com.hello {
exports com.hello;
}
- exports … to: it is used to restrict the exported packages from the modules to specific modules.
module com.hello {
exports com.hello to com.greetings;
}
- open: is used to indicate the packages that are accessible only at runtime and also available for introspection via Reflection APIs.
open module com.hello {
}
- opens: is used when not the entire model needed to be accessible but a specific packages.
module com.hello {
opens com.hello;
}
- opens…to: similar to “opens”, but only specific packages can access it.
module com.hello {
opens com.hello to com.greetings;
}
- uses: is used to indicate the service interface or abstract class that this module is using.
module com.greetings {
uses com.hello.HelloWorldInterface;
}
- provides … with: it is used to indicate that it provides implementations, identified after the with keyword, for the service interface identified after the provides keyword
module com.hello {
provides com.hello.HelloWorldInterface with com.hello.HelloWorldImpl;
}
REPL & JShell
Until Java 8, writing snippets of code required writing classes and main method, it didn’t matter how simple the snippet, it was always the same. Here is a code that prints hello world with only five lines of code !!!
public class Hello{
public static void main(String[] args) {
System.out.println("Hello World!")
}
}
Java 9 introduced REPL(Read-Evaluate-Print-Loop) and JShell, which provided an interactive shell for quickly prototyping, debugging, and learning Java and Java APIs, without the need to create classes and main method. Now all you need to do is to write the JShell command then write your code.
$ jshell
| Welcome to JShell -- Version 11.0.4
| For an introduction type: /help intro
jshell> System.out.println("Hello World!");
Hello World!
jshell>
A New HTTP Client
Java 9 has it own HTTP client in java.net package. Truth be told, it is still lacking when comparing it with google, Apache … etc clients. But still a good step in the right direction.
URL url = new URL("https://example-test.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
Interface Private Method
In addition to interfaces public abstract methods, static methods, and default methods, Java 9 has a private methods. Java 9 allowed us to include private methods in interfaces, so if two default methods needed to share code, a private method would do the trick without exposing that private method to the implementing classes.
Interfaces private methods had four rules to use them:
- cannot be abstract.
- used only inside interface.
- can be used inside other static and non-static interface methods.
- non-static methods cannot be used inside private static methods.
Example:
public interface HelloInterface
{
default String sayHelloTo(String name) {
return sayHello(name);
}
default int sayHellowWorld() {
return sayHello("world");
}
private int sayHello(String name) {
return "Hello " + name + "!!";
}
}
Unified JVM Logging
Java 9 comes with a unified logging architecture that pipes messages, which the JVM generates similar to known logging frameworks such as Log4j. It provides a common mechanism to handle all the platform logs and can be customized according to your need and the applications nature while reducing the project dependencies since it uses the JDK packages.
Here is a good example on how to use it.
Immutable Set
Prior to java 9, developers needed to use Collections.unmodifiableSet()
in order to create immutable set, which needed to add some boilerplate code to handle some special cases. Now, java 9 introduced Set.of()
which creates a set with the following characteristics:
- Structurally immutable: elements cannot be added or removed. Calling any mutator method will always cause
UnsupportedOperationException
to be thrown. null
element is not allowed: attempts to create them withnull
elements result inNullPointerException
.- Set serializable if all elements are serializable.
- Duplicate elements rejected at creation time. Duplicate elements passed to a static factory method result in
IllegalArgumentException
.
Optional to Stream
Java 9 added three useful methods to the Optional class, which are or()
, ifPresentOrElse()
and stream()
.
or()
: returns anotherOptional
lazily if the usedOptional
objectis empty. If the firstOptionalhas
a defined value, then the lambda passed to theor()
method will not be invoked.ifPresentOrElse()
: takes two actions, if the value present, will perform the first action, else it will invoke the second action.stream():
It allows the developer to use theStream
APIs for theOptional
object, if theOptional
is not present then it will create an empty stream.
Java 9 has huge changes, many of which were used in other programming languages such as Python and Scala. I didn’t cover everything as there are more exciting features and tools not mentioned here, I would recommend checking the documentation, it has a great “what’s new” session.
sources: