Core Java

New Features in Java 16

Java 16, released in March 2021, introduced several features and enhancements. Let us delve into Java 16 new features.

1. Java 16 Vector API Incubator (JEP-338)

The JIT Compiler enhances arithmetic algorithms by automatically converting certain scalar operations (individual items) into vector operations (multiple items simultaneously). However, developers previously lacked control over this process, and not all scalar operations could be transformed into vector operations. This JEP introduces a new Vector API within an incubator module, jdk.incubator.vector. This module enables developers to explicitly perform vector operations, allowing for reliable runtime compilation into optimal vector hardware instructions.

2. Records (JEP-395)

Java 14 introduces the preview feature of a new class type called records to simplify the creation of immutable data objects. Java 15 builds upon the record type, and in Java 16, records have become a standard feature of the JDK.

Below is a simplified example to illustrate the records:

public class AppMain {
    public static void main(String[] args) {
        StudentRecord student = new StudentRecord(1, "John", "Wick", "VI", 12);
        System.out.println(student.id());
        System.out.println(student.name());
        System.out.println(student);
    }
}

record StudentRecord(int id,
                     String name,
                     String section,
                     String className,
                     int age) {
}

Here are some advantages of using records:

  • Conciseness: Records reduce boilerplate code by automatically generating methods such as toString(), equals(), and hashCode(). This leads to more readable and maintainable code with fewer lines.
    // Without record
    class Point {
    private final int x;
    private final int y;
    
    public Point(int x, int y) {
       this.x = x;
       this.y = y;
    }
    
    public int getX() {
       return x;
    }
    
    public int getY() {
       return y;
    }
    
    @Override
    public boolean equals(Object obj) {
       // Implementation
    }
    
    @Override
    public int hashCode() {
       // Implementation
    }
    
    @Override
    public String toString() {
       // Implementation
    }
    }
    
  • Immutability: Records promote immutability by defaulting to final fields. Once a record instance is created, its state cannot be changed, making it inherently thread-safe.
  • Readability: The concise syntax of records enhances code readability. Records express the intent of the code more directly, making it easier for developers to understand the structure and purpose of the data.
  • Automatic equals() and hashCode(): Records automatically generate equals() and hashCode() methods based on the fields declared in the record. This ensures that two record instances with the same values are considered equal and have the same hash code.
  • Named Accessors: Records provide named accessors for their components, allowing you to access fields using more meaningful names without the need for explicit getter methods.
    Point point = new Point(10, 20);
    int x = point.x(); // Named accessor
    int y = point.y();
    
  • Compatibility with Existing Code: Records are designed to be compatible with existing Java code. You can use records alongside traditional classes and other features without any issues.

3. Pattern Matching for instanceof (JEP-394)

Java 16 introduced Pattern Matching for the instanceof operator as part of JEP-394 (JEP stands for JDK Enhancement-Proposal & Roadmap Process). This feature simplifies the common use case of casting an object after checking its type with instanceof.

Here’s an example of how you can use Pattern Matching for instanceof in Java 16:

public class InstanceOfExample {
    public static void main(String[] args) {
        Object obj = "Hello, Java 16!";

        // Traditional way
        if (obj instanceof String) {
            String str = (String) obj;
            System.out.println("Length of the string: " + str.length());
        } else {
            System.out.println("Not a String");
        }

        // Using Pattern Matching for instanceof (Java 16+)
        if (obj instanceof String str) {
            System.out.println("Length of the string: " + str.length());
        } else {
            System.out.println("Not a String");
        }
    }
}

In the second if statement, obj instanceof String str not only checks if obj is an instance of String but also casts it to the variable str within the scope of the if block. This makes the code more concise and eliminates the need for an explicit cast.

Note that this feature is available starting from Java 16, so you’ll need to use a JDK version of 16 or higher to compile and run code that includes this feature.

4. Sealed Classes (JEP-397)

Java 16 introduces sealed classes as part of JEP-397. Sealed classes provide a mechanism to control which classes can be subclasses. They achieve this by specifying a limited set of subclasses. This helps create more maintainable and secure code by explicitly defining the hierarchy. Here are several advantages associated with the use of sealed classes:

  • Improved code readability
  • Enhanced security by controlling the subclassing
  • Facilitates better maintenance of class hierarchies

Let’s consider a simple example of sealed classes in Java 16:

sealed class Shape permits Circle, Square, Triangle {
// Common methods and fields
}

final class Circle extends Shape {
// Circle-specific implementation
}

final class Square extends Shape {
// Square-specific implementation
}

final class Triangle extends Shape {
// Triangle-specific implementation
}

In this example, the Shape class is sealed, and it explicitly permits the subclasses Circle, Square, and Triangle.

4.1 Advantages of Sealed Classes (JEP-397)

  • Enhanced Security: Sealed classes allow you to control which classes can be subclasses. This helps prevent unauthorized or unintended extension of classes, enhancing the security of your code.
  • Improved Code Readability: By explicitly specifying the permitted subclasses, sealed classes clarify which classes are intended to extend them. This improves code readability and makes the class hierarchy more transparent.
  • Enforces Design Intent: Sealed classes express the design intent of a limited set of subclasses. This intentional restriction aids in designing more maintainable and predictable class hierarchies.
  • Reduced Bugs and Errors: By restricting the set of subclasses, sealed classes help reduce bugs and errors related to unexpected subclassing. This is particularly beneficial in large codebases or when collaborating with multiple developers.
  • Facilitates Pattern Matching: Sealed classes work seamlessly with pattern matching introduced in Java. This combination enables concise and expressive code when dealing with complex class hierarchies.

5. Java 16 Other Changes

Here are additional significant modifications brought about in Java 16.

  • JEP 347: Enablement of C++14 Language Features. C++ 14 features are now accessible in C++ source code with JDK 16.
  • JEP 357, JEP 369: Migration from Mercurial to Git/GitHub. The OpenJDK source code has been transitioned from Mercurial to Git/GitHub.
  • JEP 376: ZGC – Concurrent Thread-Stack Processing. The Z Garbage Collector has been enhanced by relocating its thread-stack processing from safe points to the concurrent phase.
  • JEP 380: Unix-Domain Socket Channels. Both SocketChannel and ServerSocketChannel now provide support for Unix Domain sockets.
  • JEP 386: Alpine Linux Port. The JDK is now compatible with Alpine Linux and other Linux distributions utilizing the musl implementation.
  • JEP 387: Elastic Metaspace. Metaspace memory management is refined by promptly returning unused HotSpot class metadata or metaspace memory to the operating system, resulting in a reduced metaspace footprint and simplified metaspace code.
  • JEP 388: Windows/AArch64 Port. The JDK can now operate on AArch64, including ARM hardware servers and ARM-based laptops.
  • JEP 389: Foreign Linker API (Incubator). Java code can be invoked by C/C++ or vice versa using a novel API, replacing the traditional JNI.
  • JEP 390: Warnings for Value-Based Classes. Alerts are triggered when value-based classes are synchronized using synchronize.
  • JEP 392: Packaging Tool. jpackage is now an established feature rather than an incubator feature.
  • JEP 393: Foreign-Memory Access API (Third Incubator). Minor enhancements have been introduced to the Foreign Memory Access API.
  • JEP 396: Strongly Encapsulate JDK Internals by Default. The default mode of the --illegal-access option is now set to deny. Previously, it was permitted.

6. Java 16 Depreciation and Removals

  • ThreadGroup Methods: Methods such as stop, destroy, isDestroyed, setDaemon, and isDaemon in ThreadGroup are deprecated and will be removed in a future release. The API/mechanism for destroying a thread group is considered flawed, and methods supporting explicit or automatic destruction of a thread group are terminally deprecated.
  • Signal Chaining APIs: Signal Chaining APIs like sigset and signal are obsolete, and their usage is deprecated. The cross-platform sigaction is the supported API for multi-threaded processes.
  • java.security.cert APIs: APIs representing Distinguished Names (DNs) as Principal or String objects are deprecated.
  • Elliptic Curves: Obsolete or inadequately implemented elliptic curves from the SunEC provider have been removed.
  • java.awt.PeerFixer Class: The non-public class java.awt.PeerFixer is removed. Its purpose was to provide deserialization support for ScrollPane objects created before JDK 1.1.1.
  • jaotc and Graal: The experimental Java Ahead-of-Time compilation tool, jaotc, is removed. The experimental Java-based JIT compiler, Graal, is also removed.
  • Root Certificates: Root certificates with weak 1024-bit RSA public keys have been removed from the cacerts keystore.

7. Java 16 Garbage Collectors

Java 15 has elevated the Z Garbage Collector (ZGC) to the status of a standard feature. Formerly an experimental feature, ZGC is recognized for its low latency and high scalability.

Initially introduced in Java 11, ZGC was designated as experimental because the developer community deemed it too substantial for an early release.

ZGC demonstrates exceptional performance, particularly in handling extensive datasets, such as those found in machine learning applications. It ensures minimal pause times during data processing, effectively mitigating interruptions caused by garbage collection. Furthermore, it offers compatibility with Linux, Windows, and MacOS.

In Java 16, ZGC’s Thread-Stack processing has undergone significant improvements. The transition from Safepoints to the Concurrent Phase has greatly enhanced its efficiency. The following enhancements have been incorporated.

8. Conclusion

In conclusion, Java 16 continues to strengthen its position as a modern and versatile programming language by introducing features that enhance developer productivity, code readability, and runtime performance. Whether through the refinement of existing functionalities or the introduction of new capabilities, Java 16 underscores its commitment to staying relevant in a rapidly evolving software development landscape. Developers are encouraged to explore and leverage these advancements to build robust and efficient applications.

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button