Java 15 Features

Java 15, released in September 2020, introduced a range of new features and enhancements, continuing to improve the Java platform. This guide explores the key features of Java 15, including new garbage collectors, string methods, and experimental features. It also covers performance improvements, deprecations, and other changes in this release.

1. Text Blocks

What are Text Blocks?

Text blocks, introduced as a standard feature in Java 15, provide a way to define multi-line string literals in a more readable and maintainable way. This feature was previously a preview in Java 13 and 14.

Example

public class TextBlocksExample {
    public static void main(String[] args) {
        // Using a text block to define a multi-line string
        String json = """
                      {
                          "name": "Java",
                          "version": 15,
                          "features": ["Text Blocks", "Sealed Classes"]
                      }
                      """;

        System.out.println("JSON:\n" + json);
    }
}

Output:

JSON:
{
    "name": "Java",
    "version": 15,
    "features": ["Text Blocks", "Sealed Classes"]
}

Explanation

  • Multi-Line Strings: Text blocks use triple quotes (""") to define multi-line string literals, preserving the formatting and indentation of the source code.
  • Readability: Text blocks improve the readability of multi-line strings by eliminating the need for escape sequences and concatenation, making them easier to read and maintain.

2. New Garbage Collectors: ZGC + Shenandoah

ZGC: A Scalable Low-Latency Garbage Collector

ZGC (Z Garbage Collector) is a scalable, low-latency garbage collector designed to handle large heaps and provide minimal pause times. It was introduced as an experimental feature in earlier Java versions and is now fully supported in Java 15.

  • Low Latency: ZGC minimizes pause times by performing most of its work concurrently with the application, making it suitable for applications with large heaps and high performance requirements.
  • Scalability: ZGC is designed to scale with large heap sizes, providing efficient garbage collection for memory-intensive applications.

Shenandoah: A Low-Pause-Time Garbage Collector

Shenandoah is a low-pause-time garbage collector introduced in Java 15. It is designed to reduce pause times by performing concurrent garbage collection, making it suitable for applications that require responsive performance.

  • Concurrent Collection: Shenandoah performs garbage collection concurrently with the application, reducing pause times and improving application responsiveness.
  • Low Pause Times: By minimizing pause times, Shenandoah provides more predictable performance for applications with high memory demands.

3. New String and CharSequence Methods

Java 15 introduces several new methods in the String and CharSequence classes, enhancing their functionality and usability.

String.formatted()

The String.formatted() method allows you to create formatted strings using a simpler syntax. It provides a more readable alternative to String.format().

Example

public class StringFormattedExample {
    public static void main(String[] args) {
        String name = "Java";
        int version = 15;

        // Using String.formatted() to create a formatted string
        String message = "Welcome to %s version %d".formatted(name, version);

        System.out.println(message);
    }
}

Output:

Welcome to Java version 15

Explanation

  • Formatted Strings: The formatted() method provides a simpler syntax for creating formatted strings, improving readability and usability.
  • Readability: By eliminating the need for a separate String.format() call, the formatted() method makes code more concise and readable.

String.stripIndent()

The String.stripIndent() method removes common leading whitespace from each line in a string. It is useful for cleaning up text blocks and improving readability.

Example

public class StringStripIndentExample {
    public static void main(String[] args) {
        String textBlock = """
            Line 1
            Line 2
            Line 3
        """;

        // Remove leading whitespace from each line
        String stripped = textBlock.stripIndent();

        System.out.println("Stripped Text:\n" + stripped);
    }
}

Output:

Stripped Text:
Line 1
Line 2
Line 3

Explanation

  • Indentation Removal: The stripIndent() method removes common leading whitespace from each line, improving the readability of multi-line strings.
  • Text Blocks: This method is particularly useful for cleaning up text blocks, ensuring consistent indentation and formatting.

String.translateEscapes()

The String.translateEscapes() method replaces escape sequences in a string with their corresponding characters. It simplifies working with strings that contain escape sequences.

Example

public class StringTranslateEscapesExample {
    public static void main(String[] args) {
        String escapedString = "Java\\n15";

        // Translate escape sequences into characters
        String translated = escapedString.translateEscapes();

        System.out.println("Translated String: " + translated);
    }
}

Output:

Translated String: Java
15

Explanation

  • Escape Translation: The translateEscapes() method translates escape sequences into their corresponding characters, simplifying the process of working with strings that contain escape sequences.
  • Readability: By converting escape sequences into characters, this method improves the readability and usability of strings.

CharSequence.isEmpty()

The CharSequence.isEmpty() method checks whether a CharSequence is empty. It provides a convenient way to determine if a character sequence contains any characters.

Example

public class CharSequenceIsEmptyExample {
    public static void main(String[] args) {
        CharSequence emptySeq = "";
        CharSequence nonEmptySeq = "Java";

        System.out.println("Is emptySeq empty? " + emptySeq.isEmpty());
        System.out.println("Is nonEmptySeq empty? " + nonEmptySeq.isEmpty());
    }
}

Output:

Is emptySeq empty? true
Is nonEmptySeq empty? false

Explanation

  • Empty Check: The isEmpty() method provides a convenient way

to check whether a CharSequence is empty, improving code readability and usability.

  • Readability: By providing a direct method for checking emptiness, this method enhances the readability and clarity of code that works with character sequences.

4. Helpful NullPointerExceptions

Java 15 continues to improve helpful NullPointerExceptions, which provide more detailed information about the cause of a NullPointerException. This feature enhances debugging by pinpointing which variable was null, making it easier to identify and fix issues.

Example

public class HelpfulNPEExample {
    public static void main(String[] args) {
        String[] array = null;
        try {
            // This will cause a NullPointerException
            System.out.println(array.length);
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }
}

Output:

java.lang.NullPointerException: Cannot read the array length because "array" is null
    at HelpfulNPEExample.main(HelpfulNPEExample.java:6)

Explanation

  • Detailed Information: Helpful NullPointerExceptions provide a detailed message indicating which variable was null, making it easier to identify the source of the exception.
  • Improved Debugging: This feature improves the debugging process by providing more context and information about the exception, reducing the time needed to diagnose and fix issues.

5. Performance Changes

Disable and Deprecate Biased Locking

Biased locking is a technique used to reduce the overhead of uncontested synchronization by allowing a thread to bias a lock towards itself. Java 15 disables and deprecates biased locking, as its benefits are outweighed by its complexity and potential performance issues.

  • Overhead Reduction: Biased locking reduces synchronization overhead for uncontested locks, but its complexity and potential performance issues outweigh its benefits.
  • Deprecation: By deprecating biased locking, Java 15 simplifies the locking mechanism and improves overall performance.

Specialized Implementations of TreeMap Methods

In Java 15, the TreeMap class introduced specialized implementations for several methods, including putIfAbsent, computeIfAbsent, computeIfPresent, compute, and merge. These new implementations improve performance but come with specific considerations regarding the modification of the map within the provided functions.

Key Methods with Specialized Implementations in Java 15:
  1. putIfAbsent
  2. computeIfAbsent
  3. computeIfPresent
  4. compute
  5. merge

Important Considerations

  • Performance Improvement: The new implementations provide enhanced performance for the respective methods.
  • ConcurrentModificationException: If the function provided to compute or merge modifies the map, a ConcurrentModificationException may be thrown. To avoid this, ensure that the provided function does not modify the map, or rewrite the code to use conventional methods like get and put.

6. Experimental, Preview, and Incubator Features

Sealed Classes (Preview)

Sealed classes, introduced as a preview feature in Java 15, allow you to restrict which classes can be extended or implemented. This feature enhances encapsulation and provides more control over class hierarchies.

Example

public sealed class Shape permits Circle, Square {
}

public final class Circle extends Shape {
}

public final class Square extends Shape {
}

Explanation

  • Class Hierarchy Control: Sealed classes restrict which classes can extend or implement them, providing more control over class hierarchies and improving encapsulation.
  • Encapsulation: By limiting the inheritance of sealed classes, this feature enhances encapsulation and reduces the risk of unauthorized modifications.

Pattern Matching for instanceof (Second Preview)

Pattern matching for instanceof, reintroduced as a preview feature in Java 15, simplifies type casting by allowing you to test and cast an object in a single expression. This feature reduces boilerplate code and improves readability.

Example

public class PatternMatchingExample {
    public static void main(String[] args) {
        Object obj = "Java 15";

        // Using pattern matching for instanceof
        if (obj instanceof String str) {
            System.out.println("Length: " + str.length());
        }
    }
}

Output:

Length: 7

Explanation

  • Simplified Casting: Pattern matching for instanceof eliminates the need for explicit casting, allowing you to declare a variable of the target type within the instanceof expression.
  • Improved Readability: By reducing boilerplate code, pattern matching for instanceof improves the readability and maintainability of Java applications.

Records (Second Preview)

Records, reintroduced as a preview feature in Java 15, provide a concise way to declare data classes. A record is a special kind of class in Java that automatically provides implementations for equals(), hashCode(), and toString() methods, reducing boilerplate code.

Example

public record Point(int x, int y) {
    // No need to implement equals(), hashCode(), or toString()
}

public class RecordsExample {
    public static void main(String[] args) {
        Point point = new Point(5, 10);
        System.out.println("Point: " + point);
    }
}

Output:

Point: Point[x=5, y=10]

Explanation

  • Concise Syntax: Records provide a concise syntax for defining data classes, automatically generating implementations for common methods.
  • Immutable Data: Records are implicitly final and provide immutable data, ensuring data integrity and reducing the risk of errors.

Foreign-Memory Access API (Second Incubator)

The Foreign-Memory Access API, reintroduced as an incubator feature in Java 15, provides a way to access foreign memory outside of the Java heap. This API allows developers to work with native memory more efficiently and safely.

Example

import jdk.incubator.foreign.MemorySegment;
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.Pointer;

public class ForeignMemoryAccessExample {
    public static void main(String[] args) {
        try (MemorySegment segment = MemorySegment.allocateNative(4)) {
            MemoryAddress baseAddress = segment.baseAddress();
            Pointer<Integer> intPointer = baseAddress.asPointer();

            intPointer.set(42);
            System.out.println("Value: " + intPointer.get());
        }
    }
}

Output:

Value: 42

Explanation

  • Native Memory Access: The Foreign-Memory Access API allows developers to access and manipulate native memory outside of the Java heap, providing more flexibility and control over memory management.
  • Safety and Efficiency: This API provides safety and efficiency when working with foreign memory, reducing the risk of memory-related errors and improving performance.

7. Deprecations and Deletions

Remove the Nashorn JavaScript Engine

The Nashorn JavaScript Engine, introduced in Java 8, is removed in Java 15. It has been deprecated since Java 11 due to the availability of more modern and efficient JavaScript engines.

Remove the Solaris and SPARC Ports

Java 15 removes the Solaris and SPARC ports, as these platforms are no longer widely used or supported. This removal allows the Java platform to focus on more relevant and widely-used platforms.

Deprecate RMI Activation for Removal

RMI Activation is a feature of Java RMI (Remote Method Invocation) that allows remote objects to be activated on demand. Java 15 deprecates RMI Activation for removal, as it is rarely used and has limited practical applications.

8. Other Changes in Java 15

Hidden Classes

Hidden classes are a new feature in Java 15 that allows developers to define classes that are not discoverable through reflection. This feature is useful for frameworks and libraries that need to dynamically generate classes at runtime.

Edwards-Curve Digital Signature Algorithm (EdDSA)

The Edwards-Curve Digital Signature Algorithm (EdDSA) is a new cryptographic algorithm introduced in Java 15. It provides a secure and efficient way to generate and verify digital signatures.

Java 15 provides developers with access to modern cryptographic algorithms, improving the security and performance of their applications.

Reimplement the Legacy DatagramSocket API

Java 15 reimplements the legacy DatagramSocket API to improve its performance, scalability, and maintainability. This change enhances the efficiency and reliability of network communication in Java applications.

Compressed Heap Dumps

Java 15 introduces compressed heap dumps, which reduce the size of heap dump files by using compression. This feature improves the efficiency of memory analysis and debugging.

Support for Unicode 13.0

Java 15 supports Unicode 13.0, which includes additional characters, scripts, and emoji. This support enhances Java's ability to handle diverse character sets and languages, improving internationalization capabilities.

Conclusion

Java 15 introduces several key features and improvements, including text blocks, new garbage collectors, and enhanced string methods. These features enhance developer productivity, application performance, and the flexibility of the Java platform. By understanding and leveraging these features, developers can build more efficient and maintainable Java applications.

For a complete list of all changes in Java 15, refer to the official Java 15 release notes.

Series: Java Release-wise New Features

Comments