Fundamentals 15 min read

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.

macrozheng
macrozheng
macrozheng
Unlock Java’s Latest Power: Practical Guide to New Features from Java 9‑17

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 1248

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)

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.

Javaprogrammingcode examplesnew-featuresjava-17
macrozheng
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.