JDk 16

2021 04 01 head

I truly love the new release rhythm of the Java ecosystem. It is awesome to be able to use new features every six months.

The migration overhead is held to a minimum thanks to incredible backward compatibility.

The new features greatly simplify the existing code and tremendously increase legibility.

Features like records, sealed types, or switch expressions are wonderful. The promise of advanced pattern matching constructs is sweet.

Polishing of functional programming approach improved my source code quite stupendously.

New Features

Java 16 fully supports Algebraic Data Types with the record and sealed types features.

An immutable data class including a constructor, getters, equals(Object o), hashCode(), and toString() can be declared in one line:

public record Person(int id, String firstname, String lastname) {}

The first step with modern pattern matching constructs was provided with Pattern Matching for Instanceof.

As a small but nice gain of pattern matching, you can now implement the boolean equals(Object o) method in Java in one statement and without if clause. An example would be:

public boolean equals(Object o) {
    return (o instanceof Key that) && name == that.name && Arrays.equals(ptypes, that.ptypes);
}

The other new features are more of an internal nature.

Notice that Alpine Unix is now officially supported. This port is great new to shrink the size of docker images containing a Java runtime.

Troubles With Some Packages

MicroStream

MicroStream persistence library crashes if you are using records.

ArchUnit

ArchUnit crashes if you are using records. [1]

Jacoco

Jacoco has trouble handling records and generating spurious error messages.

Gradle

Gradle still does not work natively with JDK 16. They at least provide a well-documented and workable approach. You can run the tool with JDK 15 and compile your components with JDK 16. Use the instruction toolchain { languageVersion = JavaLanguageVersion.of(16) }. One of the cool stable features of the Gradle release 7.0 is the full support for the Java module system. You can now build, test, and run Java modules via Gradle with the java library plugin. The mere presence of module-info.java will let Gradle infer that your jar is a module and has to be put on the module path. [2]

The huge drawback of the Gradle workaround is that you need two installed JDKs in your CI image. Standard images do not support this configuration. You have to create your own images if you are running Gradle with a Java version and compiling your application with another one.

Records were announced more than a year ago. It is a wake-up call to maintainers of Java libraries such as ArchUnit, SonarLint, or Jacoco.

Please do not be laggards. Do not force us to work with legacy Java programming paradigms. Support modules, auto-closeable resources, records, sealed classes.

As a maintainer of a successful component or application, you should represent modern Java approaches. Did you realize that since Java 8, a new version is released every six months?

The Next Changes I am Dreaming Of

Concise Method Body

Syntactic sugar to write compact delegation classes. It provides the same mechanisms for method overwriting as for lambda declarations [3].

Switch Type Selection

We can already chain if else if statements with instanceof operator and variable declarations. I want to do the same in a switch statement.
I have good news. The JEP for pattern matching for switch statements (JEP 406) and for record and array patterns (JEP 405) have candidate status in April 2021 [4].

More Packages Support Modules

Java modules were introduced with Java 8. I really, really, really want to use modules in Java 16. Therefore, I need a module version for all mainstream Java libraries. Until now, the Java developers' community has failed us; support for modules is abysmal.

Important Remainder

The next long-term supported Java shall be published in September 2021. The evolution between LTS 11 and LTS 17 is huge. Quite a lot of companies are still stocked with LTS 8. Modern Java code written with the current Java version is very different to older coding paradigms.

Companies must now implement modernization approaches if they want to survive in the business world. A security flaw with an older Java version moves on thin ice if your customers sue your company.

Especially if you do not have one of these expensive support and security packages sold by Oracle for legacy Java versions.

It should be a strategic goal for every company to have a clear migration concept for all Java applications to be ported to LTS Java version 17. This LTS version should be removed in September 2021. Early releases are already available to support migration initiatives. This migration shall be implemented through teams until the end of year 2021.


1. ArchUnit 0.18.0 was released on 14 April 2021. Records are now supported. They are still working on supporting sealed types.
2. Gradle 7.0 was released 09 April 2021. JDK 16 is now supported as runtime for Gradle. You can have a regular build for your application with JDK 16 and Gradle in your CI pipeline. Gradle engine has been upgraded to using Groovy 3 in Groovy-based DSL build scripts to fully support JDK 16.
3. I had to accept that this feature will not be part of the LTS release Java 17.
4. First extensions for pattern matching will be part of the preview functionality of the LTS release Java 17.