What's new in Java 16?

Everything you wanted to know about Java 16 but were too scared to ask!

Bcorp Logo
Coffee Beans

Java 16, aka Oracle’s Java Development Kit (JDK) 16, was released on March 16, 2021.

It should be noted that this release is not a LTS (or Long-Term Support) version; that will be Java 17. This means that Java 16 will only be supported for 6 months as Java 17 is expected in September 2021.

This raises the question “why bother with Java 16?” or alternatively “Can I just ignore Java 16 then?”. The answer to this is you should be interested in Java 16 because it is either introducing or previewing new language features and enhancements which will impact on any application that will eventually use Java 17. It is thus a useful way to explore these changes and determine the impact on your project / application / future development plans etc. You can then factor any required reengineering into your schedules.

In fact, this is the purpose of the frequent, six monthly releases, provided by Oracle between the main LTS releases (which appear every three years). They allow Oracle to make new features available to developers earlier and quicker than would be the case if the only releases were the 3 yearly LTS versions.

In addition, each new release tends to include a smaller number of new features than was the case with the old big bang approach of a major release every few years. This is illustrated by the following chart, which illustrates the number of new releases in some of the Java versions between Java 8 and Java 16:

What's new in Java 16?

It also allows Oracle to preview new ideas / proposals in the form of technology previews or incubator modules. Oracle can then gauge the developer community reaction to these proposals and either adopt them in a future release or amend them and include modified previews in the next release.

If you look at the Java 12 through to Java 16 releases, we have seen the introduction of previews for sealed classes and interfaces, as well as the previews, and now the introduction of new language features for Records

and Pattern Matching for instanceof.

To help developers understand the purpose or role of a feature, Oracle categorises each new feature as one of:

  • Preview – this indicates that the associated feature is a preview of what might be released in a future version of Java. However, it is being made available to allow developers to provide feedback and thus any future version may change from that included in this release.
  • Future Proofing – this usually indicates that a feature has been introduced to ensure that future versions of Java can make changes to the language without negatively affecting application code (as long as it has adhered to whatever feature was previously used to provide future proofing).
  • New Language Feature - as it says it is a new language feature which has usually been previwed at least once in previous version of java.
  • Incubator modules – these are modules that contain features that are not yet standardized and could benefit from further experience in order to either be proven or disproven. They are more experimental that previews.
  • Productivity Improvement – is a feature aimed to make life easier for developers.
  • JVM Improvement – represents some aspect of the JVM which has been revised / enhanced / reimplemented.
  • New Tool/Library – which is exactly what it says!

The 17 new features (and the category that feature falls into) in Java 16 are:

  • Sealed Classes / Interfaces (Second Preview)
  • Strongly Encapsulate JDK Internals by Default (Future Proofing)
  • Records (New Language Features)
  • Pattern Matching for instanceof (New Language Features)
  • Foreign-Memory Access API (Third Incubator)
  • Packaging Tool (New Tools and Libraries)
  • Warnings for Value-Based Classes (Future Proofing)
  • Foreign Linker API (Incubator)
  • Windows/AArch64 Port (Improving Productivity)
  • Elastic Metaspace (JVM Improvements)
  • Alpine Linux Port (Improving Productivity)
  • Unix-Domain Socket Channels (New Tools and Libraries)
  • ZGC: Concurrent Thread-Stack Processing (JVM Improvements)
  • Migrate to GitHub (Improving Productivity)
  • Migrate from Mercurial to Git (Improving Productivity)
  • Enable C++14 Language Features (Improving Productivity)
  • Vector API (Incubator)

Of these the features that are probably of most interest to developers for current application development are the New Language Features such as Records and ‘Pattern Matching for instanceof’. However, developers should also examine the Sealed Classes Preview and the introduction of the future proofing feature for Warnings for Value-Based Classes. We will look briefly at each of these in the remainder of this blog.


Records were first introduced as a preview feature in Java 14 and again with some modification in Java 15. Records are what some other languages might refer to as data classes (see Kotlin data classes or Scala case classes). That is, they are wrappers around immutable values that provide additional semantics to the immutable data. They also supply default implements of equals() and toString() as well as default accessors.

For example, the following Point class illustrates a typical implementation for a data-oriented type with two immutable values (x and y). This takes 20 or more lines in old style Java; most of which would be boiler plate code:

class Point {
    private final int x;
    private final int y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;

    int x() { return x; }
    int y() { return y; }

    public boolean equals(Object o) {
        if (!(o instanceof Point)) return false;
        Point other = (Point) o;
        return other.x == x && other.y == y;

    public int hashCode() {
        return Objects.hash(x, y);

    public String toString() {
        return String.format("Point[x=%d, y=%d]", x, y);

Using records all of this is replaced with:

record Point(int x, int y) { }

Pattern Matching for instanceof

The aim of Pattern Matching with instanceof feature (previewed in Java 14 and 15) is to simplify those situations in which the behaviour of some subtype must be invoked that is not defined at the super type level.

For example, in old style Java you might encounter some code that uses a if statement to determine if a variable references a specific type of thing and then to do something based on that type. 

For example:

Object obj = …
if (obj instanceof String) {
    String s = (String) obj;

In the new syntax the above can be more concisely implemented as:

Object obj = …
<b>if</b> (obj <b>instanceof</b> String s) {

Within the if statement the contents of obj is now bound to the variable s which is automatically of type String.

Sealed Classes / Interface Preview

Sealed classes were introduced as a preview feature in Java 15, this is therefore the second preview for this new language feature. A sealed class or interface can only be extended or implemented by those classes and interfaces that are explicitly permitted to do so in the same module (if the sealed type is defined in a named module) or the same package (if the unnamed module is being used). That is when the sealed class or interface is defined it can explicitly declare classes or interfaces that can extend or implement it.

For example, if the following declaration is defined within the unnamed module:

public abstract sealed class Shape
    permits Circle, Rectangle, Square { ... }

In this case Shape is an abstract sealed class that can only be extended by the Circle, Rectangle and Square classes that must be defined near to Shape in the same package.

Warnings for Value-Based Classes Future Proofing

This is an attempt to future proof application code against future language changes. Any code written for Java 16 (or compiled with Java 16) that does not generate any warnings will be compatible with the current plan for Value-Based classes. To this end all basic or fundamental types such as int and double and their wrapper types java.lang.Integer, java.lang.Double etc., are now considered Value-based types. As such to avoid future issues all explicit instantiations of Integers and Doubles using new have been deprecated (note this does not affect implicit boxing and unboxing). In addition, if a compile time option is turned on, then all code that attempts to synchronize on instances of class such as Integer and Double will produce compile time warnings.


None of these changes may seem earth-shattering, but they are worth at least watching. The future of Value-Based types and the use of Records seem particularly significant. In addition, sealed classes, which are used in Kotlin and Scala, may well become a powerful way to control what can extend a class or implement an interface.

Did you find this article interesting and useful?

...then you will love our Java training courses, where you'll gain solid hands-on experience, guided by an industry expert. All our Java classes are available to attend online as virtual instructor-led training courses.

Share this post on:

We would love to hear from you

Get in touch

or call us on 020 3137 3920

Get in touch