Java 23 extends import and patterns, but dispenses with string templates
In addition to enhanced preview features such as the Class-File API, the JDK brings innovations in pattern matching and opens up the documentation for Markdown.
(Image: Erstellt mit Dall-E von iX-Redaktion)
OpenJDK 23 has been released on a six-monthly cycle. Like its predecessor, the release brings twelve Java Enhancement Proposals (JEP), most of which are in the preview phase.
Many JEPs continue the proposals launched in Java 21 and Java 22. There are also two initial previews in the current JDK. In addition to innovations to the language and the libraries, there are also extensions to the documentation and improvements to the garbage collector. Finally, the JDK heralds the end of unsafe memory access via sun.misc.Unsafe.
However, string templates are missing in Java 23 and will only be reintroduced into the language later in a revised design.
Videos by heise
Patterns with primitive types
The previous Java versions brought some innovations for pattern matching, which enable elegant handling when processing data structures. "JEP 455: Primitive Types in Patterns, instanceof, and switch" is a new preview that enables the use of primitive data types within pattern matching for the first time. This means that not only direct numerical values or reference types such as integer and string are permitted in case conditions, but also primitive types such as byte or int, as in the following example from the proposal:
switch (x.getYearlyFlights()) {
case 0 -> ...;
case 1 -> ...;
case 2 -> issueDiscount();
case int i when i >= 100 -> issueGoldCard();
case int i -> //... appropriate action when i > 2 && i < 100 ...
}
The type of the variable in the switch statement does not have to correspond to the data types in the individual conditions. Similarly, instanceof results in true regardless of the variable type, provided the variable can be converted safely:
float f = 1000.0f;
f instanceof double; // true
f instanceof int; // true, da konvertierbar
f instanceof byte; // false, da jenseits des Raums von byte
The type is not converted in the process, but the result is only true if a lossless conversion is possible. The same applies to record patterns.
Simple import
Also marked as the first preview is "JEP 476: Module Import Declarations (Preview)", which simplifies the import of packages by including all packages that a module exports. For example, import java.base provides all 54 packages defined in the module, such as java.io, java.net and java.security, thus eliminating the need for separate import via the individual commands such as import java.io.*.
Applications must explicitly resolve potential ambiguities. For example, the Date class exists both in java.util, which is contained in the java.base module, and in java.sql. When importing both modules, applications that use Date must specify the import to be used:
import module java.base;
import module java.sql;
import java.sql.Date; // bestimmt die zu verwendende Date-Klasse
Date d = new Date(); // verwendet die Klasse aus java.sql
More convenience for constructors and for main
The "JEP 477: Implicitly Declared Classes and Instance Main Methods" first appeared in Java 21 as "JEP 445: Unnamed Classes and Instance Main Methods". Above all, it simplifies the call of the main method and requires less boilerplate code. Among other things, the classic and previously not really minimalistic Hello World program is significantly simplified:
//klassisches Hello World
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
//minimalistisches Hello World mit JEP 477
void main() {
println("Hello, World!");
}
More flexibility in the constructor is the goal of "JEP 482: Flexible Constructor Bodies". In the second preview, it continues the proposal introduced in Java 22 as "JEP 447: Statements before super(...)". The JEP breaks with the old rule that no code is allowed before super if a Java constructor calls the constructor of the superclass.
Thanks to the new feature, programs can, for example, check parameters to detect errors and avoid overhead before the superclass constructor is called in accordance with the fail-fast principle:
public class PositiveBigInteger extends BigInteger {
public PositiveBigInteger(long value) {
if (value <= 0) throw new IllegalArgumentException(..);
super(value);
}
}
In addition, it is now possible to perform complex parameter calculations for the constructor of the superclass in the child class.
Insight into the classes and extended stream processing
Java 22 also included the first previews for processing classes and streams, which Java 23 continues. "JEP 466: Class-File API" provides an API for parsing, creating and converting the files of Java classes. As a standard for the Java core, it should be able to process class files as well as third-party tools, including ASM or Apache Commons BCEL (Byte Code Engineering Library). It is designed as a simple API that is not intended to replace external libraries.
The "JEP 473: Stream Gatherers" flows into the current JDK without any changes compared to the first preview in Java 22, and the finalization of the proposal is planned for Java 24 under JEP 485. It extends the Java Stream API with additional operations that enable the transformation of streamed data and goes further than the previous extension via Stream::collect(). However, this collector can still be located behind the gatherer, and several gatherers can be combined in the form stream.gather(...).gather(...).collect(...). The transformation via the gatherers can take place in 1:1, 1:n, n:1 or n:m relation.