Fundamentals 12 min read

Unlock Java 9‑16: Key Features Every Developer Should Know

This article quickly walks through the major language and JVM enhancements introduced in Java 9 through Java 16—including private interface methods, var type inference, switch expressions, records, sealed classes, new garbage collectors, and tooling updates—so developers can stay current and write more concise, efficient code.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Unlock Java 9‑16: Key Features Every Developer Should Know

Java has been releasing new versions at a breakneck pace, with Java 8 introducing lambdas and streams, and subsequent releases (9‑16) adding numerous language and JVM enhancements.

Java 9 (2017)

Private methods in interfaces

Java 9 allows defining private methods inside interfaces, which can be invoked from default methods, enabling code reuse without exposing the methods.

public interface TestInterface {
    default void wrapMethod() {
        innerMethod();
    }
    private void innerMethod() {
        System.out.println("");
    }
}

Diamond operator for anonymous classes

The diamond operator <> now works with anonymous inner classes, allowing type inference without explicit generic type declarations.

List<Integer> numbers = new ArrayList<>();
List<Integer> numbers = new ArrayList<>() {
    ...
};

Enhanced try‑with‑resources

Java 9 lets resources declared outside the try block be managed automatically, simplifying code when multiple resources are used.

BufferedReader br0 = new BufferedReader(...);
BufferedReader br1 = new BufferedReader(...);
try (br0; br1) {
    System.out.println(br0.readLine() + br1.readLine());
}

Java 10 (2018)

Local variable type inference (var)

The new var keyword infers the type of a local variable, reducing boilerplate.

var message = "Hello, Java 10";

Java 11 (2018)

var in lambda parameters

Lambda parameters can now be declared with var, allowing annotations and modifiers.

List<String> languages = Arrays.asList("Java", "Groovy");
String language = sampleList.stream()
    .map((@Nonnull var x) -> x.toUpperCase())
    .collect(Collectors.joining(", "));

Single‑file source‑code execution

Java 11 enables running a single source file directly with the java command.

$ java HelloWorld.java
Hello Java 11!

Java Flight Recorder open‑sourced

JFR is now part of OpenJDK, providing low‑overhead profiling and diagnostics.

Java 12 (2019)

Switch expression

Switch statements become expressions that can return values and support comma‑separated case labels.

typeOfDay = switch (dayOfWeek) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Working Day";
    case SATURDAY, SUNDAY -> "Day Off";
};

Pattern matching for instanceof

Instanceof now performs a type cast automatically when the pattern matches.

Object obj = "Hello Java 12!";
if (obj instanceof String str) {
    int length = str.length();
}

Java 13 (2019)

Enhanced switch with yield

Switch can now contain a block with yield to return a value.

typeOfDay = switch (dayOfWeek) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
        // do sth...
        yield "Working Day";
    }
    case SATURDAY, SUNDAY -> "Day Off";
};

Text blocks

Multi‑line string literals are supported via text blocks, simplifying JSON or SQL strings.

String json = """
{
    "id":"1697301681936888",
    "nickname":"空无",
    "homepage":"https://juejin.cn/user/1697301681936888"
}
""" ;

Java 14 (2020)

Records

Records provide a compact syntax for immutable data carriers.

public record UserDTO(String id, String nickname, String homepage) { }

Helpful NullPointerException messages

JDK 14 improves NPE messages to indicate exactly which variable was null.

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Boolean.booleanValue()" because the return value of "java.util.Map.get(Object)" is null
    at org.example.App.main(App.java:50)

Foreign‑memory access API

Safe APIs replace Unsafe for off‑heap memory operations.

// allocate 200 bytes of native memory
MemorySegment segment = MemorySegment.allocateNative(200);
// write a long value
VarHandle vh = MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder());
vh.set(segment.baseAddress(), 10L);
segment.close();

jpackage tool

jpackage creates native installers and runtime images, eliminating the need to ship a separate JRE.

Java 15 (2020)

ZGC and Shenandoah GC

Both low‑pause collectors become production‑ready.

Sealed classes

Sealed classes restrict which other classes or interfaces may extend or implement them.

public sealed interface Service permits Car, Truck {
    int getMaxServiceIntervalInMonths();
    default int getMaxDistanceBetweenServicesInKilometers() { return 100000; }
}

Java 16 (2021)

Java 16 finalizes many preview features introduced in earlier releases.

Summary

Understanding these features helps developers stay productive and avoid being left behind as Java evolves rapidly.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaprogrammingJDKVersion Featureslanguage updates
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

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.