Java 16 Features : A Guide of Java 16 Features

In this Java Tutorial, we will see all new Java 16 Features. We will understand, what new packages, classes and functionalities have been added in Java 16. We will also learn, How can we take advantage of these Java 16 features to solve generic as well as critical problems in a much more simpler way. So, Let’s get started –

Java 16 released with 17 new features

The year 2020 was a memorable year for all the Java Developers as we celebrated the 25th birthday of Java. Surprisingly, with over 2 decades Java has successfully provided a whole lot of support to develop different software solutions for all major and minor requirements. It gracefully took advantage of OOPs, Inheritance, Multithreading as well as Lambda Expressions, Stream APIs, and now, 17 new functionalities have been added as features in Java 16.

Java has proved that it’s more flexible by adapting to the changing technological landscapes. The March 16, 2021 is the Java 16 release date. However, there is no official notification of LTS (Long Term Support) of Java 16. The Java version 11 is the currently supported LTS version.



Java 16 Features : Timestamp & Count

As per the Oracle’s 6 month release cycle, the Java 17 is expected to be the 2nd LTS (Long-Term Support) release after Java 11 since switching to the new 6-month release cadence. Let’s have a look at all major releases of Java –

More than 15 features are included in Java 15 to make use of Java 16 Features.

It’s notable that, after the release of Java 11, the version that included the maximum number of features is the Java 16. As, a quick summary, here are all those Java 16 features –

Java 16 Features & Specification

Along with a number of performance, stability and security updates, Java 16 provided these major enhancements or changes with one preview feature –

1) Records : Specs 395
2) Sealed Classes (a preview) : Specs 397
3) Pattern Matching for instanceof : Specs 394
4) Strongly Encapsulate JDK Internals by Default : Specs 396
5) Foreign-Memory Access API (Third Incubator) : Specs 393
6) The Vector API (Incubator) : Specs 338
7) Enable C++14 Language Features : Specs 347
8) Migrate from Mercurial to Git : Specs 357
9) Migrate to GitHub : Specs 369
10) ZGC: Concurrent Thread-Stack Processing : Specs 376
11) Unix-Domain Socket Channels : Specs 380
12) Alpine Linux Port : Specs 386
13) Elastic Metaspace : Specs 387
14) Windows/AArch64 Port : Specs 388
15) Foreign Linker API (Incubator) : Specs 389
16) Warnings for Value-Based Classes : Specs 390
17) Packaging Tool : Specs 392

1. Records

The ‘record‘ is a new type of class that helps to easily create immutable data objects. It was first introduced as a preview feature in Java 14 and again in Java 15. Records provide another way for declaring classes using a compact syntax which are transparent holders for shallowly immutable data. Let’s understand this feature with an example –

Without using record :

public class Student {

    private final String name;
    private final int age;

    public Student(String name, int age) { = name;
        this.age = age;

    public String getName() {
        return name;

    public int getAge() {
        return age;

Notice that there’re a number of statements to create an immutable object that really just holds the state. The above example is to create immutable object of class Student without using record.

As, all of our fields such as name and age are explicitly defined using final, we have a single all-arguments constructor, and we have an accessor method for every field. In some cases, we might even declare the class itself as final to prevent any sub-classing.

In some cases, with the above example, we can go one step ahead, and can override the toString(), equals() and hashcode() methods for getting some meaningful results.


Using record :

public record Student(String name, int age) { }

When using record, we can define the same immutable Student object in a concise way like above. A few things happened here in the above statement are –

1) First, the class Student defined with a brand new keyword record, which is specific for records.

2) Second, when the compiler reaches at this header, it automatically defines all the required member variables and accessors.

3) We also do not to provide any constructor for it.

4) Additionally, the compilar provides a default implementations to the toString(), equals() and hashcode() methods.

5) Finally, you must remember that, records are always final, and they cannot be declared abstract.

2) Sealed Classes (Another Preview)

It a preview feature and was there in Java 15 as well. Such features restrict, which other classes or interfaces may extend or implement them. Its core use is to provide fine-grain control on access specifiers (such as public/private/protected) in Java.

The major goal of sealed classes is to allow individual classes to declare which types may be used as sub-types. The same restriction applies to interfaces and determining which types can implement them.

Sealed classes involve two new keywords — sealed and permits :

public abstract sealed class Person
    permits Student, Teacher {

    // Other regular code...


In the above example, we’ve declared an abstract class named Person. Then, we’ve specified that the only classes that can extend our Person are Student and Teacher.

3) Pattern Matching

The pattern matching is now a new feature in Java. However, It was introduced in Java 14 and Java 15 as a preview feature.

As a Java 16 feature, the goal of this feature is to remove a whole lot of boilerplate code that typically comes whenever try to use the instanceof operator in Java :

if (thePerson instanceof Student) {

    Student theStudent = (Student) thePerson;
    Date dob = theStudent.getDateOfBirth();

    // Other statements...

It’s a very common pattern of use of instanceof operator. Whenever, we check whether an object is of some type, most of the time, the next statement casts the object to that type.

Using this feature of Java 16, we can bind a variable immediately after verifying the instantiation check, something like this –

if (thePerson instanceof Student theStudent) {

    Date dob = theStudent.getDateOfBirth();       // No need of type casting and instantiation statement ...

    // Other statements...

In the above example, we had not instantiated theStudent object, and got it inside the if condition. We provided a new variable name theStudent as part of the instanceof check. Here, the JVM automatically casted the object reference and assigned it into theStudent – the new binding variable.

4) Encapsulating the JDK Internal Elements

This feature is for futureproofing our work, which strongly encapsulates all the internal elements of the JDK by default. However, it does not encapsulate a critical internal APIs such as sun.misc.Unsafe. According to this feature, the Code successfully compiled with earlier releases that accesses internal APIs of the JDK, may no longer work by default. This change aims to encourage Java developers to migrate from using internal elements to using standard APIs.

5) Foreign Memory Access API

Its already an incubating feature in Java 14 and Java 15 as well. Now, in Java 16, its major goals of this API are –

  • To allows Java programs to safely and efficiently operate on various kinds of foreign memory (e.g., native memory, persistent memory, managed heap memory, etc.).
  • It also provides the foundation for the Foreign Linker API.
  • Support for parallel processing of a memory segment using the Spliterator interface.
  • Better support for mapped memory segments.

The term “Foreign Memory” basically refers to the memory that lives outside the managed JVM heap. And, because of this, It’s out of the range of garbage collection and can typically handle incredibly large memory segments.

Other Major Features

There are no doubt, a number of other changes in Java 16 that are notable –

  • The Vector API is there in Java 16 as an incubator. It helps to achieve superior performance. This API will allow developers to easily write performant and portable vector algorithms in Java.
  • Warnings for Value-based classes (such as java.lang.Integer, java.lang.Double).
  • A brand new Packaging Tool Library. It was first introduced as an incubator in Java 14. This new library supports native packaging formats to give end users a natural installation experience.
    These formats include msi and exe on Windows, pkg and dmg on macOS, and deb and rpm on Linux.


Wrapping Up 

There are no doubt a number of essential enhancements in Java 16. This version of Java targets to reduce some critical overheads of developments like removing boiler-plate code, better and secure code reusability with Java Inheritance, and several others.

However, some of the features of Java 16 are under incubation or preview, still you need to learn other changes and libraries added into it, to be a better Java developer. Here is the list of some Better Java Programming resources for you –

Course - Java 16 Features and Concepts

Hope, this post helped you to enhance your Java knowledge +1 level up. Don’t forget to share its link on social media – To show, What you know! Thanks for reading 😀
Sharing is Caring …

Leave a Comment