A Practical Overview of New Java Features from Java 9 to Java 17
This article presents a concise, hands‑on review of the most useful Java language enhancements introduced between Java 9 and Java 17—including private interface methods, Optional API upgrades, var type inference, the new HTTP client, switch expressions, text blocks, records, instanceof pattern matching, and sealed classes—illustrated with clear code examples.
Since Java 9, the language has added many practical features that improve code reuse, readability, and safety without adding unnecessary complexity. This article focuses on those features that directly affect developers' daily coding.
Interface Private Methods (Java 9)
Java 9 allows private methods inside interfaces, enabling default methods to share common logic without duplication.
public interface MyInterface {
default void method1() {
System.out.println("Default method1");
commonMethod();
}
default void method2() {
System.out.println("Default method2");
commonMethod();
}
/** This is the shared logic */
private void commonMethod() {
System.out.println("Common method in the interface");
}
}Both method1() and method2() call the private commonMethod(), eliminating duplicated code.
Optional API Enhancements (Java 9)
The new stream() method and ifPresentOrElse() simplify handling optional values.
Optional<String> optional = ...;
optional.ifPresent(value -> System.out.println(value.length()));With Java 9:
Optional<String> optional = ...;
optional.stream().map(String::length).forEach(System.out::println);And the ifPresentOrElse construct:
Optional<String> optionalValue = Optional.of("Hello");
// Java 8
if (optionalValue.isPresent()) {
System.out.println("Value is present: " + optionalValue.get());
} else {
System.out.println("Value is absent");
}
// Java 9
optionalValue.ifPresentOrElse(
value -> System.out.println("Value is present: " + value),
() -> System.out.println("Value is absent")
);Stream API Enhancements (Java 9)
New methods takeWhile, dropWhile, ofNullable, and an overloaded iterate give finer control over stream processing.
Stream.of("a", "b", "c", "de", "f")
.takeWhile(s -> s.length() == 1)
.forEach(System.out::print); // Prints "abc" Stream.of("a", "b", "c", "de", "f")
.dropWhile(s -> s.length() == 1)
.forEach(System.out::print); // Prints "def"Local Variable Type Inference (Java 10)
The var keyword lets the compiler infer the type of local variables, reducing boilerplate.
var str = "Hello, World!"; // String
var num = 123; // int
var list = new ArrayList<String>(); // ArrayList<String>
for (var i = 0; i < 10; i++) {
System.out.println(i);
}
try (var reader = new BufferedReader(new FileReader("file.txt"))) {
// use reader
}New HTTP Client (Java 11)
The modern HTTP client API replaces HttpURLConnection and supports HTTP/2, synchronous and asynchronous calls.
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("http://example.com"))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());Asynchronous example:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("http://example.com"))
.build();
CompletableFuture<HttpResponse<String>> future =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
future.thenAccept(response -> {
System.out.println(response.statusCode());
System.out.println(response.body());
});Switch Expression Enhancements (Java 12)
Switch can now be used as an expression, reducing boilerplate.
int day = 2;
String dayOfWeek = switch (day) {
case 1 -> "Monday";
case 2 -> "Tuesday";
case 3 -> "Wednesday";
case 4 -> "Thursday";
case 5 -> "Friday";
case 6 -> "Saturday";
case 7 -> "Sunday";
default -> throw new IllegalArgumentException("Invalid day: " + day);
};
System.out.println(dayOfWeek); // Prints "Tuesday"Text Blocks (Java 13)
Multiline string literals are now possible with """ syntax, supporting optional interpolation.
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
System.out.println(html);Record Classes (Java 14)
Records provide a compact syntax for immutable data carriers.
public record Point(int x, int y) { }The compiler automatically generates constructor, equals(), hashCode(), toString(), and accessor methods.
Instanceof Pattern Matching (Java 16)
The instanceof operator can now bind a variable, removing the need for explicit casts.
Object obj = ...;
if (obj instanceof String str) {
System.out.println(str.length());
}Sealed Classes and Interfaces (Java 17)
Sealed types restrict which classes may extend or implement them, improving type safety.
public abstract sealed class Shape permits Circle, Square { }Only Circle and Square can subclass Shape. The non‑sealed modifier can be used to relax this restriction.
These features collectively modernize Java, making code more concise, expressive, and maintainable.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
