New Features in Java 20
Hello. In this tutorial, we will talk about the new features introduced in Java 20.
1. New Features in Java 20
The Java 20 release has officially designated seven key features, which encompass virtual threads, a vector API proposal, structured concurrency, scoped values, a foreign function and memory API, record patterns, and pattern matching for switch statements and expressions.
1.1 Virtual Threads
Virtual Threads, a prerequisite for structured concurrency, have undergone some modifications since their first preview in JDK 19. These changes include a few adjustments to the API and permanent degradations to ThreadGroup. As they enter the second preview stage, these lightweight threads aim to simplify the development and maintenance of concurrent applications with high-throughput demands. Oracle believes that this enhancement will lead to a significant transformation in how Java applications are scaled. The updates made since the initial preview in JDK 19 involve a small number of API changes (now permanent in JDK 19) and degradations to ThreadGroup (also now permanent in JDK 19).
1.2 Vector API Proposal
In the earlier JDK versions (16, 17, 18, and 19), the Vector API was introduced as an incubation project. However, shortly before the launch of Java 20, this API proposal underwent re-incubation with no changes to the API from its state in JDK 19. The implementation process included fixing a few bugs and enhancing performance. Now, this new proposal allows the expression of vector computations that efficiently compile at runtime, acting as optimal vector instructions on supported CPUs. The official addition of the Vector API occurred only a few weeks ago. Its purpose is to enable the expression of vector computations that compile at runtime into highly efficient vector instructions on supported CPU architectures. This leads to significantly improved performance compared to equivalent scalar computations. Thus, the Vector API had been previously incubated in JDK 16, JDK 17, JDK 18, and JDK 19 before its official inclusion.
1.3 Structured Concurrency
Structured Concurrency introduces an API that simplifies multithreaded programming by treating multiple tasks, executed in different threads, as a cohesive unit of work. This approach streamlines error-handling and cancellation processes, leading to improved reliability and better observability of the application’s behavior. The only modification made since its incubation in JDK 19 is the enhancement of StructuredTaskScope to enable the inheritance of scoped values by threads created within a task scope. Currently, this feature is undergoing reincubation. Initially introduced as an incubating API in JDK 19, Structured Concurrency significantly eases multithreaded programming by considering multiple tasks running in separate threads as a single unit of work. This approach streamlines error handling and cancellation, leading to increased reliability and improved observability. The sole change during its re-incubation is the update to StructuredTaskScope, enabling threads created in a task scope to inherit scoped values.
1.4 Scoped Values
The incubating API, Scoped Values, facilitates the sharing of immutable data both within and among threads. It serves as a preferable alternative to thread-local variables, especially in scenarios involving a substantial number of virtual threads. By utilizing scoped values, data can be safely and efficiently shared between various components within a large program, eliminating the need for method arguments. The primary objectives of this API include ensuring ease of use, comprehensibility, robustness, and performance. Currently, in the incubator stage of development, the Scoped Values API addresses the need for sharing immutable data within and between threads. This approach is favored over thread-local variables, particularly when dealing with a significant number of virtual threads. With scoped values, sharing data between different components in a large program becomes both secure and efficient, without the necessity of resorting to method arguments. The API aims to achieve goals of usability, clarity, resilience, and optimal performance.
1.5 Foreign Function and Memory (FFM) API
The Foreign Function and Memory (FFM) API allows Java programs to interact with code and data external to the Java runtime, enabling calls to native libraries and handling of native data without the complexity and risks associated with JNI (Java Native Interface). This API had been previously incubated in JDK versions 17 and 18 and was previewed in JDK 19. Improvements made since JDK 19 encompass the consolidation of MemorySegment and MemoryAddress abstractions, enhancements to the Sealed MemoryLayout hierarchy, and the division of MemorySession into Arena and SegmentScope, facilitating the sharing of segments across maintenance boundaries.
The FFM API combines two earlier incubating APIs, namely the Foreign-Memory Access API and the Foreign Linker API. Initially incubated in JDK 17, then re-incubated in JDK 18, it was later previewed in JDK 19. Based on valuable user feedback, JDK 20 now re-previews the FFM API, incorporating the following enhancements:
- MemorySegment and MemoryAddress abstractions are unified, now representing memory addresses through zero-length memory segments.
- The Sealed MemoryLayout hierarchy is improved to facilitate seamless usage with pattern matching in switch expressions and statements.
- MemorySession has been divided into Arena and SegmentScope, promoting the sharing of segments across maintenance boundaries.
1.6 Record Patterns
The second preview of Record Patterns in Java aims to achieve two primary goals: extending pattern matching to enable more advanced and composable data queries and maintaining the syntax and semantics of type patterns. This language feature was initially introduced in JDK 19, and in Java 20, users can expect the following updates:
- Added support for inferring type arguments of generic record patterns.
- Support for record patterns to be used in the header of an enhanced
for
statement. - Removal of support for named record patterns.
Record patterns introduce a powerful mechanism in the Java programming language that allows for deconstructing record values. By nesting record patterns and type patterns, developers can perform data navigation and processing in a declarative and efficient manner. The main objectives of this feature are to enhance pattern-matching capabilities and maintain consistency in type pattern syntax and semantics. Notable changes since the first preview in JDK 19 involve the addition of type argument inference for generic record patterns, enabling record patterns in the header of an enhanced for statement, and the removal of named record pattern support.
Sample code snippet
public record Position(int x, int y) {}
1.7 Pattern Matching for Switch Statements and Expressions
Pattern Matching, introduced as a preview in JDK 17 and further advanced in JDK 18 and JDK 19, now enters its fourth preview stage with JDK 20. This evolution ensures its continued progress alongside the Record Patterns preview feature, incorporating essential updates to the switch statement’s grammar. Pattern matching for switch statements and expressions offers a concise and secure way to handle intricate data-oriented queries. The fourth preview, following its earlier appearances in JDK 17, JDK 18, and JDK 19, allows for ongoing co-evolution with the Record Patterns feature, benefiting from continuous refinements based on practical experience and user feedback.
The primary changes in pattern matching for the switch since the third preview involve the streamlining of grammar for switch labels and the support for type argument inference in generic patterns and record patterns used within switch statements and expressions. Additionally, in case of an exhaustive switch over an enum class, a MatchException will be thrown instead of an IncompatibleClassChangeError if no switch label is applicable at runtime.
Sample code snippet
Object obj = getObject(); switch (obj) { case String s when s.length() > 5 -> System.out.println(s.toUpperCase()); case String s -> System.out.println(s.toLowerCase()); case Integer i -> System.out.println(i * i); default -> {} }
2. Conclusion
In conclusion, the development of Java has seen significant advancements in recent versions, including the introduction of various features and language enhancements. Notably, the latest preview of Java, JDK 20, showcases several pivotal updates, such as the incorporation of Pattern Matching and Record Patterns, which are designed to simplify data-oriented queries and promote a more concise and secure coding approach.
The fourth preview of Pattern Matching, building on its prior appearances in JDK 17, JDK 18, and JDK 19, reaffirms its position as a crucial language feature. By facilitating switch statements and expressions, Pattern Matching enables developers to express complex queries efficiently and safely, streamlining code and improving readability. The addition of support for an inference of type arguments in generic patterns and record patterns used within switch statements enhances its flexibility and usability.
Furthermore, the continued co-evolution of Pattern Matching with the Record Patterns preview feature underscores Java’s commitment to refining and optimizing language constructs based on practical experience and user feedback. This iterative development process ensures that both Pattern Matching and Record Patterns evolve in tandem, harmonizing their functionality and usability for developers.
As Java progresses, it strives to cater to the ever-evolving needs of developers and maintain its position as a robust, reliable, and innovative programming language. The enhancements in JDK 20, especially about Pattern Matching and its collaboration with Record Patterns, exemplify Java’s dedication to providing a modern, efficient, and user-friendly development environment for a wide range of applications. Developers can look forward to leveraging these powerful features in their projects to create more expressive, maintainable, and efficient codebases. With each iteration, Java’s evolution showcases its adaptability and responsiveness to the evolving landscape of software development, solidifying its status as a cornerstone language in the programming community.