Java 22: All new features explained
Java 22 debuted, and it's a great time to look at the new features. It's important to note that this is the first version after the Long-Term Support (LTS) release, Java 21, so there will be many new features in the incubator or preview stage. The new version introduces 12 JEPs (JDK Enhancement Proposals). We will discuss all of them.
Java Syntax Changes
Since Java 8, many syntactic constructions familiar from other languages have been added. One such feature is the unnamed variables and patterns (JEP-456), which has become stable in Java 22.
In many languages, such as Python or JavaScript, it's common to assign unused variables to _. Until now, this wasn't an option in Java, so if a variable was not needed, it still had to be named. Now, this is no longer necessary. For example, instead of:
static int count(Iterable<Order> orders) {
int total = 0;
for (Order order : orders) // order is unused
total++;
return total;
}
In Java 22, you can write:
static int count(Iterable<Order> orders) {
int total = 0;
for (Order _ : orders) // Unnamed variable
total++;
return total;
}
Similarly, this can be done for patterns:
switch (ball) {
case RedBall _ -> process(ball); // Unnamed pattern variable
case BlueBall _ -> process(ball); // Unnamed pattern variable
}
Other changes in the new version are not yet stable, but we will quickly go over them.
The first of these is the ability to execute instructions before using super in the constructor (JEP-447). Previously, super should be called first, and then other instructions could be added. Technically, it was possible to have code before super, but there were several conditions that had to be met, which complicated things and ultimately made it not very useful in most scenarios. This was frustrating, especially if the subclass had to perform some logic to, for example, check if the arguments made sense. This can, of course, lead to extra work.
Thanks to this change, it will be possible, for example, to do something like this:
public class PositiveBigInteger extends BigInteger {
public PositiveBigInteger(long value) {
if (value <= 0)
throw new IllegalArgumentException("non-positive value");
super(value);
}
}
Other JEPs related to language are known from previous versions of Java, either as a preview or from the incubator. These include:
- JEP-459: String templates, i.e., interpolation on steroids.
- JEP-453: Classes and main declared indirectly, an option to shorten Hello World in Java.
Both of these features were discussed when Java 21 was released.
Code Support Outside JVM
Java has introduced two new features related to this.
Firstly, we have JEP-454, which adds an API for handling foreign functions and memory. The first effects of work on this API were available in Java 17, in 2021. Since then, each version of Java has added new features to these APIs, and now we finally have a stable version.
The goal of the new API is to replace JNI with something more stable, but also written in pure Java, fast, and safe. So, if you use JNI in your work, it's worth checking if the new API fits your requirements.
Speaking of JNI, JEP-423 introduces so-called Region Pinning for the G1 garbage collector. The goal is to avoid having to turn off GC for critical regions in JNI, so the effect should be better memory management.
Other Interesting New Features
JEP-457 is interesting, introducing a new API for modifying Java classes. The goal is to eliminate ASM and provide a better tool for creating and modifying Java classes using code. This will be useful for many tool developers assisting in coding, probably less so for ordinary programmers. This is a preview feature.
In Java 11, it became possible to run a single, uncompiled Java file with a simple command. Now, however, more files can be run at once. Suppose we have such files:
Prog1.java
Prog2.java
Helper.java
library1.jar
library2.jar
If we run a command like:
java --class-path '*' Prog1.java
The Java launcher will load all JAR files into the classpath and find the necessary classes in the appropriate files. This is a stable feature in Java 22.
In the preview version, Java introduces so-called Stream gatherers (JEP-461), a new API for stream handling that allows performing non-standard actions on a stream (which theoretically are difficult to achieve using standard operations). It's somewhat similar to collect, but gather is designed to handle intermediate steps.
We still have 3 JEPs left to describe, but all of them have been discussed by us earlier.
The first two are related to concurrency:
- Structured concurrency (JEP-462) - which treats groups of related tasks operating on different threads as a single entity, making them easier to manage.
- Scoped variables (JEP-464) - which facilitate sharing immutable data between a thread and its children.
The next is the API for handling vectors (JEP-460). This is already the 7th version that has been warming up in the incubator. Who knows, maybe something will hatch from it soon.
Our verdict on Java 22
The fact that there are only a few stable changes in Java 22 was to be expected. In the new release cycle, usually, the first version after the LTS is mainly about introducing new concepts, which will mature to be stable and well-tested before the next LTS.
That's exactly what happened in this release. Looking at the stable functions, one can conclude that work on the foreign function and memory API took more time than planned, as it's really the only big and stable feature of Java 22. The other changes are still about adding functions known from other languages, to make the life of Java programmers easier.
At this stage, it's hard to expect a revolution in Java, and all changes reflect this. We're dealing with the slow improvement of syntax and fixing of underperforming systems.