Java 22: What’s new?
JDK 22 reached General Availability on 19 March 2024. Let’s quickly explore the main additions that Java 22 brings to the table with straightforward code examples to illustrate the power of these new features.
Unnamed Variables & Patterns
First introduced in Java 21 as a preview, Java 22 makes unnamed variables and patterns a standard feature, a feature that allows developers to use an underscore (_) for unused variables, making code cleaner and more readable. Example:
// Before Java 22
for (int unusedVariable = 0; unusedVariable < myList.size(); unusedVariable++) {
// Perform an action that doesn't use the element itself
System.out.println("Processing completed"));
}
// Java 22 with underscores
for (_ = 0; _ < myList.size(); _++) {
// Perform an action that doesn't use the element itself
System.out.println("Processing completed"));
}In this example, we process a list of numbers, but we don’t need to use the number itself within the loop. The underscore _ signifies that the variable is intentionally unnamed and unused.
Statements before super(...)
The ability to execute statements before calling super(...) in constructors is now in preview. This feature provides more flexibility in initializing objects. Example:
class Parent {
Parent(int number) { /* ... */ }
}
class Child extends Parent {
Child(int number) {
int processedNumber = number * 2; // Statement before super
super(processedNumber);
}
}String Templates (Second Preview)
String templates, now in their second preview, allow for embedding expressions within string literals, simplifying the way dynamic strings are created. Example:
String name = "Java";
String greeting = $"Welcome to {name} 22!";
System.out.println(greeting); // Output: Welcome to Java 22!The $"..." syntax denotes a string template, and {name} is an expression that gets evaluated and included in the string.
Implicitly Declared Classes and Instance Main Methods (Second Preview)
Java 22 simplifies the code for small, single-class programs by allowing classes and main methods to be implicitly declared. Example:
// No public class declaration needed
public static void main(String[] args) {
System.out.println("Simplified Java class structure!");
}This code snippet is a complete Java program without an explicit class declaration, making it easier for beginners to start coding.
Foreign Function & Memory API
Java 22 introduces the final version of the Foreign Function & Memory API (FFI).
This powerful tool allows Java programs to interact with code and data written in other languages like C or C++.
Previously, integrating code from other languages involved a complex tool called JNI. Now, the FFI offers a simpler and safer way to call functions written in other languages directly from your Java code. It also allows you to access and manipulate memory used by these external functions.
Get Tech Proverb’s stories in your inbox
Join Medium for free to get updates from this writer.
For example, imagine you have a powerful C library for handling complex image processing tasks. With the FFI, you can leverage the capabilities of that library within your Java program, potentially achieving superior performance compared to writing everything in Java. Example:
// Import FFI classes
import io.foreign.*;
public class TinyFFI {
public static void main(String[] args) {
// Linker to access C library (replace with actual library)
Linker linker = Linker.nativeLinker();
// Assuming a C function called "doSomething" exists
MemoryAddress functionAddress = linker.lookup("myClib.so", MemoryAddress.class, "doSomething");
// Interact with the C function using FFI (simplified)
useCFunction(linker, functionAddress);
System.out.println("Called C function");
}
// Simplified method representing FFI interaction (replace with actual logic)
private static void useCFunction(Linker linker, MemoryAddress address) {
// Replace with actual FFI interaction based on function signature
// (e.g., calling the function, passing arguments, handling return value)
}
}In this example, we use the Foreign Function & Memory API to lookup the doSomething function inside the C library and then subsequently call this function for further processing from within the useCFunction method.
Stream Gatherers (Preview)
Stream gatherers are a new feature in Java 22 that allow you to customize how you process data in a stream.
Scenario: Imagine you have a stream of numbers and you want to collect them into groups of 3.
Before Java 22:
You might achieve this using multiple methods from the Stream API:
List<List<Integer>> groupsOfThree = numbers.stream()
.collect(Collectors.toList()) // Collect all elements into a list
.stream() // Create a new stream from the list
.windowed(3, 1) // Group elements into windows of size 3 with a step of 1 (no overlap)
.collect(Collectors.toList()); // Collect each window (group) into a listThis approach involves creating multiple intermediate streams and collecting them into lists.
Java 22 with Stream Gatherers:
With stream gatherers, you can achieve the same result in a more concise way:
List<List<Integer>> groupsOfThree = numbers.stream()
.gather(Gatherers.windowFixed(3)) // Use windowFixed gatherer with size 3
.toList(); // Collect the resulting groups into a listInstead of chaining multiple methods, we instead use the gather method with a gatherer. The gatherer we use is Gatherers.windowFixed(3). This built-in gatherer groups elements into fixed-size windows of 3. Finally, we call toList() to collect the resulting groups (windows) into a list of lists.
Summary
As seen with previous releases, the Java 22 release also contains features that promote cleaner code, streamline development workflows, and unlock performance optimizations. With these enhancements, Java continues to be an attractive choice for building modern, efficient, and scalable applications.









