Java 14 Features

Java 14, released in March 2020, is another non-LTS (Long-Term Support) release that continues to enhance the Java platform with new features, improvements, and deprecations. This guide explores the key features introduced in Java 14, including experimental and preview features, performance improvements, and important deprecations.

1. Switch Expressions (Standard)

What are Switch Expressions?

Switch expressions, introduced as a standard feature in Java 14, provide a more concise and flexible way to use the switch statement. This feature, previously a preview in Java 12 and 13, allows the switch statement to be used as an expression, improving readability and reducing boilerplate code.

Conciseness: Switch expressions allow for more compact code by eliminating the need for break statements. 

Returning Values: Switch expressions can return values, making them useful for assignments and more versatile than traditional switch statements. 

Pattern Matching: Switch expressions support pattern matching, enabling more complex and readable conditions.

Example

public class SwitchExpressionsExample {
    public static void main(String[] args) {
        String day = "MONDAY";

        // Using switch as an expression with yield
        int result = switch (day) {
            case "MONDAY", "FRIDAY", "SUNDAY" -> 6;
            case "TUESDAY" -> 7;
            case "THURSDAY", "SATURDAY" -> 8;
            case "WEDNESDAY" -> {
                int len = day.length();
                yield len; // Using yield to return a value
            }
            default -> throw new IllegalArgumentException("Invalid day: " + day);
        };

        System.out.println("Result: " + result);
    }
}

Output:

Result: 6

Explanation

  • Expression Syntax: Switch expressions use the -> syntax to associate a case with a result, allowing for more concise and readable code.
  • Yield Statement: The yield statement is used to return a value from a switch expression block, providing a more explicit way to specify the result.
  • Improved Readability: By reducing boilerplate code, switch expressions improve the readability and maintainability of Java applications.

2. Helpful NullPointerExceptions

Java 14 introduces 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.

3. Experimental, Preview, and Incubator Features

Records (Preview)

Records, introduced as a preview feature in Java 14, provide a concise way to declare data classes. 

Records are a special kind of class in Java that are designed to model immutable data and eliminate boilerplate code associated with creating classes that are primarily used to store data.

A record class 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.

Pattern Matching for instanceof (Preview)

Pattern matching for instanceof, introduced as a preview feature in Java 14, 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 14";

        // 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.

Text Blocks (Second Preview)

Text blocks, reintroduced as a preview feature in Java 14, provide a way to define multi-line string literals. This feature simplifies the creation of strings that span multiple lines, making them more readable and less error-prone.

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": 14,
                          "features": ["Text Blocks", "Switch Expressions"]
                      }
                      """;

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

Output:

JSON:
{
    "name": "Java",
    "version": 14,
    "features": ["Text Blocks", "Switch Expressions"]
}

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.

ZGC on macOS + Windows (Experimental)

Java 14 extends the Z Garbage Collector (ZGC) to support macOS and Windows platforms. ZGC is a low-latency garbage collector designed for applications with large heaps, providing minimal pause times and improved performance.

Explanation

  • Platform Support: By extending ZGC to macOS and Windows, Java 14 expands the availability of this low-latency garbage collector, allowing more developers to take advantage of its benefits.
  • Improved Performance: ZGC provides minimal pause times and improved performance for applications with large heaps, making it suitable for memory-intensive applications.

Packaging Tool (Incubator)

The Packaging Tool, introduced as an incubator feature in Java 14, provides a way to package Java applications into self-contained executables. This tool simplifies the deployment process and allows developers to distribute Java applications more easily.

  • Self-Contained Executables: The Packaging Tool allows developers to package Java applications into executables that include the JDK and application dependencies, simplifying deployment.
  • Cross-Platform: The Packaging Tool supports multiple platforms, allowing developers to distribute Java applications as native executables on Windows, macOS, and Linux.

Foreign-Memory Access API (Incubator)

The Foreign-Memory Access API, introduced as an incubator feature in Java 14, 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 java.foreign.memory.MemorySegment;
import java.foreign.memory.MemoryAddress;
import java.foreign.memory.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.

4. Performance Improvements

Non-Volatile Mapped Byte Buffers

Java 14 introduces non-volatile mapped byte buffers, which provide a way to map files directly into memory without requiring disk access. This feature improves performance by allowing applications to access file data more efficiently.

Explanation

  • Memory Mapping: Non-volatile mapped byte buffers map files directly into memory, allowing applications to access file data without disk I/O.
  • Improved Performance: By reducing the need for disk access, non-volatile mapped byte buffers improve the performance and responsiveness of Java applications.

NUMA-Aware Memory Allocation for G1

Java 14 enhances the G1 garbage collector with NUMA-aware memory allocation, optimizing memory usage on systems with Non-Uniform Memory Access (NUMA) architectures. This feature improves performance by aligning memory allocation with the system's architecture.

Explanation

  • NUMA Optimization: NUMA-aware memory allocation improves memory usage on systems with NUMA architectures, aligning memory allocation with the system's topology.
  • Performance Improvements: By optimizing memory allocation, NUMA-aware memory allocation improves the performance and scalability of Java applications on NUMA systems.

Parallel GC Improvements

Java 14 introduces several improvements to the Parallel garbage collector, enhancing its performance and efficiency. These improvements reduce pause times and improve the responsiveness of Java applications using the Parallel GC.

Explanation

  • Improved Efficiency: Parallel GC improvements enhance the efficiency of garbage collection, reducing pause times and improving application performance.
  • Reduced Pause Times: By optimizing garbage collection, Parallel GC improvements reduce pause times, improving the responsiveness and user experience of Java applications.

5. Deprecations and Deletions

Thread Suspend/Resume Are Deprecated for Removal

Java 14 deprecates the Thread.suspend() and Thread.resume() methods for removal, as they are inherently unsafe and can cause deadlock issues. Developers are encouraged to use safer alternatives for thread management.

Deprecate the Solaris and SPARC Ports

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

Remove the Concurrent Mark Sweep (CMS) Garbage Collector

Java 14 removes the Concurrent Mark Sweep (CMS) garbage collector, as it has been superseded by more modern and efficient garbage collectors, such as G1 and ZGC. Developers are encouraged to use these alternatives for garbage collection.

Deprecate the ParallelScavenge + SerialOld GC Combination

Java 14 deprecates the ParallelScavenge + SerialOld GC combination, as it is less efficient than other garbage collection options. Developers are encouraged to use more modern and efficient garbage collectors, such as G1 and ZGC.

Remove the Pack200 Tools and API

Java 14 removes the Pack200 tools and API, as they are no longer needed or widely used. Developers are encouraged to use modern compression formats and tools for packaging Java applications.

6. Other Changes in Java 14

JFR Event Streaming

Java 14 introduces JFR (Java Flight Recorder) event streaming, which allows continuous monitoring of application performance with low overhead. This feature enables real-time analysis of performance data, improving the ability to diagnose and resolve performance issues.

What is Accounting Currency Format Support?

Java 14 introduces accounting currency format support, which allows numbers to be formatted in an accounting-style currency format. This feature improves the flexibility and usability of the NumberFormat class for financial applications.

Example

import java.text.NumberFormat;
import java.util.Locale;

public class AccountingCurrencyFormatExample {
    public static void main(String[] args) {
        double amount = -1234.56;

        // Accounting currency format for different locales
        NumberFormat accountingFormatUS = NumberFormat.getCurrencyInstance(Locale.US);
        accountingFormatUS.setCurrency(NumberFormat.getCurrencyInstance().getCurrency());

        NumberFormat accountingFormatFR = NumberFormat.getCurrencyInstance(Locale.FRANCE);
        accountingFormatFR.setCurrency(NumberFormat.getCurrencyInstance().getCurrency());

        System.out.println("US Accounting Format: " + accountingFormatUS.format(amount));
        System.out.println("France Accounting Format: " + accountingFormatFR.format(amount));
    }
}

Output:

US Accounting Format: ($1,234.56)
France Accounting Format: -1 234,56 €

Explanation

  • Accounting Style: Accounting currency format support allows numbers to be formatted in accounting-style currency format, which is commonly used in financial applications.
  • Locale-Specific: The NumberFormat class provides locale-specific accounting currency formats, allowing developers to format numbers according to regional conventions.

Conclusion

Java 14 introduces several key features and improvements, including switch expressions, helpful NullPointerExceptions, and enhancements to garbage collectors and performance. 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 14, refer to the official Java 14 release notes.

Series: Java Release-wise New Features

Comments