Unlock Java’s Latest Power: Practical Guide to New Features from Java 9‑17
This article provides a concise, hands‑on overview of Java’s most useful language enhancements from Java 9 through Java 17—including private interface methods, Optional API upgrades, Stream API additions, var type inference, the new HTTP client, switch expressions, text blocks, records, instanceof pattern matching, and sealed classes—complete with clear code examples for each feature.
Introduction
The article presents a practical checklist of useful Java language features introduced from Java 9 to Java 17, focusing on real‑world coding benefits rather than low‑level runtime optimizations.
Private Interface Methods (Java 9)
Before Java 9, interfaces could only contain abstract methods and default methods. Java 9 adds private methods, allowing shared logic between default methods without code duplication.
public interface MyInterface {
default void method1() {
System.out.println("Default method1");
commonMethod();
}
default void method2() {
System.out.println("Default method2");
commonMethod();
}
private void commonMethod() {
System.out.println("Common method in the interface");
}
}Optional API Enhancements (Java 9)
Java 9 introduces stream(), ifPresentOrElse(), or(), and isEmpty() methods, simplifying optional handling.
Optional<String> optional = ...;
optional.stream().map(String::length).forEach(System.out::println);
optional.ifPresentOrElse(v -> System.out.println("Value is present: " + v),
() -> System.out.println("Value is absent"));
Optional<String> backup = Optional.of("Backup value");
Optional<String> result = optional.or(() -> backup);
System.out.println(result.get());
if (optional.isEmpty()) {
System.out.println("Optional is empty");
}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
Stream.ofNullable(null).forEach(System.out::print);
Stream<Integer> stream = Stream.iterate(1, n -> n < 10, n -> n * 2);
stream.forEach(System.out::print); // prints 1248Local 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)
Java 11 replaces HttpURLConnection with a modern, asynchronous‑friendly HTTP client API.
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());
CompletableFuture<HttpResponse<String>> future = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
future.thenAccept(r -> {
System.out.println(r.statusCode());
System.out.println(r.body());
});Switch Expression Enhancements (Java 12)
Switch can now be used as an expression, yielding a value directly.
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 of week: " + day);
};
System.out.println(dayOfWeek); // Prints "Tuesday"Text Blocks (Java 13)
Multi‑line string literals are now possible with text blocks, supporting optional interpolation via ${}.
String html = """
<html>
<body>
<p>Hello, ${name}</p>
</body>
</html>
""";
System.out.println(html);Record Classes (Java 14)
Records provide a concise way to declare immutable data carriers.
public record Point(int x, int y) { }Instanceof Pattern Matching (Java 16)
The instanceof operator can now bind a variable, eliminating 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 sealed abstract class Shape permits Circle, Square { }
public final class Circle extends Shape { }
public final class Square extends Shape { }These features collectively make modern Java 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.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.
