Java 9 introduced a range of new features and enhancements that improved the overall development experience. From the groundbreaking module system to enhancements in the Streams API and new utilities, Java 9 has a lot to offer. In this blog, we’ll delve into the most important features introduced in Java 9, along with code examples to illustrate their usage.
1. Java Platform Module System (JPMS)
The most significant feature of Java 9 is the Java Platform Module System (JPMS), also known as Project Jigsaw. This system introduces a modular approach to developing, packaging, and managing Java applications.
What is JPMS?
JPMS allows you to divide your application into modules, which can explicitly define their dependencies and expose their APIs. This helps in improving maintainability, security, and performance.
Example
// module-info.java
module com.example.myapp {
requires java.sql;
exports com.example.myapp.api;
}
2. JShell: The Interactive Java REPL
JShell is a Read-Eval-Print Loop (REPL) for Java. It allows you to execute Java code snippets interactively, which is particularly useful for learning, experimenting, and testing code quickly.
Example
$ jshell
| Welcome to JShell -- Version 9
| For an introduction type: /help intro
jshell> int x = 10;
x ==> 10
jshell> x + 20
$2 ==> 30
3. Enhanced Streams API
Java 9 introduced several enhancements to the Streams API, including new methods like takeWhile(), dropWhile(), and iterate().
Filter vs. TakeWhile/DropWhile
The filter() method processes all elements of the stream and retains only those that match the given predicate. In contrast, takeWhile() and dropWhile() are designed to work with ordered streams and process elements based on their position in the stream.
filter(): Applies the predicate to all elements in the stream, retaining only those that match the predicate.
takeWhile(): Takes elements from the stream as long as the predicate is true. Once the predicate returns false, it stops processing and returns the result.
dropWhile(): Drops elements from the stream as long as the predicate is true. Once the predicate returns false, it processes the remaining elements and returns the result.
Example
import java.util.stream.Stream;
// Using filter()
Stream.of(1, 2, 3, 4, 5, 6)
.filter(n -> n < 4)
.forEach(System.out::println); // Outputs: 1, 2, 3
// Using takeWhile()
Stream.of(1, 2, 3, 4, 5, 6)
.takeWhile(n -> n < 4)
.forEach(System.out::println); // Outputs: 1, 2, 3
// Using dropWhile()
Stream.of(1, 2, 3, 4, 5, 6)
.dropWhile(n -> n < 4)
.forEach(System.out::println); // Outputs: 4, 5, 6
Enhanced iterate() Method
Java 9 also enhanced the iterate() method, allowing it to take a predicate to specify when to stop iterating.
Stream.iterate(1, n -> n < 10, n -> n + 1)
.forEach(System.out::println); // Outputs: 1, 2, 3, 4, 5, 6, 7, 8, 9
4. Optional Class Enhancements
The Optional class received new methods like ifPresentOrElse(), or(), and stream().
Example
import java.util.Optional;
Optional<String> optional = Optional.of("Hello");
optional.ifPresentOrElse(
System.out::println,
() -> System.out.println("Value is not present")
);
Optional<String> empty = Optional.empty();
String result = empty.or(() -> Optional.of("default")).get();
System.out.println(result); // Outputs: default
5. Private Interface Methods
Java 9 allows you to define private methods in interfaces. These methods can be used to share common code between default and static methods.
Example
interface MyInterface {
default void defaultMethod() {
commonMethod();
}
static void staticMethod() {
commonMethod();
}
private static void commonMethod() {
System.out.println("Common method implementation");
}
}
class MyClass implements MyInterface {}
MyClass obj = new MyClass();
obj.defaultMethod(); // Outputs: Common method implementation
MyInterface.staticMethod(); // Outputs: Common method implementation
6. HTTP/2 Client
Java 9 introduced a new HTTP/2 client API under the java.net.http package, which supports HTTP/2 and WebSocket. This API makes it easier to perform HTTP operations.
Example
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
7. Collection Factory Methods
Java 9 introduced factory methods for creating immutable collections, which simplify the initialization of collections.
Example
import java.util.List;
import java.util.Map;
import java.util.Set;
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("X", "Y", "Z");
Map<String, Integer> map = Map.of("key1", 1, "key2", 2);
System.out.println(list);
System.out.println(set);
System.out.println(map);
8. Process API Improvements
Java 9 enhanced the Process API, allowing you to manage and control operating system processes more easily.
Example
ProcessHandle currentProcess = ProcessHandle.current();
System.out.println("PID: " + currentProcess.pid());
System.out.println("Command: " + currentProcess.info().command().orElse("Unknown"));
9. Enhanced Deprecation
Java 9 introduced enhanced deprecation, allowing API developers to specify when an element was deprecated and when it is expected to be removed.
Example
@Deprecated(since = "9", forRemoval = true)
public void deprecatedMethod() {
// Implementation
}
Conclusion
Java 9 brought a host of new features and enhancements that have greatly enriched the Java programming experience. From the modularity introduced by JPMS to the convenience of JShell, the enhanced Streams API, and the new HTTP/2 client, Java 9 provides powerful tools for modern software development. By leveraging these features, developers can write more modular, maintainable, and efficient code.
Feel free to connect with me here on LinkedIn to discuss how Java 9 can be leveraged in your projects. Happy coding!
If you liked the post, share it to your network.