Java 22 notes

Updated: 2024-04-03

ℹ️ Draft: this is a work in progress collection of notes

Official page and release date

The JDK 22 has been the 2024-03-19, it's not a LTS release, will be supported only for 6 months.

You can find the list of new features here:

https://openjdk.org/projects/jdk/22/

The official release notes can be found here:

https://jdk.java.net/22/release-notes

Spring Boot support

Spring Boot 3.3 will have GA support for Java 22. You can use previous versions of Spring Boot with Java 22, but it will be from Spring Boot 3.3 that you will get the best from the new version of Java (e.g. Spring Boot 3.2 has GA support for Java 21).

Features (JSR: title)

New

423: Region Pinning for G1
454: Foreign Function & Memory API
456: Unnamed Variables & Patterns
458: Launch Multi-File Source-Code Programs

Preview

447: Statements before super(...) (Preview)
457: Class-File API (Preview)
459: String Templates (Second Preview)
461: Stream Gatherers (Preview)
462: Structured Concurrency (Second Preview)
463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
464: Scoped Values (Second Preview)

Incubator

460: Vector API (Seventh Incubator)

447: Statement before super(...) - Preview

Until Java 22 the constructor of an extended class had to call the constructor of the parent as first statement to initialize the parent's fields (top-down / no-access-before-initialization approach).

The goal of this change is to 'relax' the rule and allow some operations before the call to the super class constructor. The same apply fot constructors chaining (calling this([args])).

Use cases:

  • validation of parameters to pass to the superclass
  • calculation of parameters to pass to the superclass
  • share superclass constructor arguments

This new feature will allow to add statements that don't use the parents field (super.)

class Parent() { 
    protected String name; 
    Parent(String name) { 
        this.name = name; 
    } 
} 
 
class Child() { 
    Child(String name, String parentName) { 
        System.out.println("I'm not changing any state! I'm harmless!!!"); // Error!!! 
        super(parentName); 
    } 
} 

In this example the System.out doesn't change the state of the Objects but Java throws an Error:

|  Error: 
|  call to super must be first statement in constructor 
|          super(parentName); 
|          ^---------------^ 

This should not be anymore the case in future releases of Java. You could use expressions that don't touch instance members of the parent.

The new grammar for constructor bodies adds a Prologue to the constructor:

ConstructorBody: 
    { [BlockStatements] } 
    { [BlockStatements] ExplicitConstructorInvocation [BlockStatements] } // Prologue: new!!! - ExplicitConstructorInvocation - Epilogue  

JEP page: https://openjdk.org/jeps/447

JEP 454: Foreign Function & Memory API https://openjdk.org/jeps/454, a.k.a. bye JNI

This new API allows the interoperability with code outside the Java runtime without the use of the Java Native Interface (JNI).

You can invoke foreign functions and native libraries without the intrusion of JNI and the connected risks (memory, limited in few languages, etc.)

You can find the new functions in the java.lang.foreign package.

In the JEP page you can find multiple examples.

If you are using JNI in your project, you should give a look to the Panama project that is working towards the improvement of the interactivity between JVM and native code and the Jextract library.

JEP 456: Unnamed Variables & Patterns https://openjdk.org/jeps/456

With the introduction of this feature you will start to see something strange in the code, '_' (U+005F) is a new feature in the language. The same char is used by other languages like Python, Swift, Scala.

'_' represents a variable that is declared but never used, you could have some use cases in which a variable or pattern must be declared, but it's not used.
In this case the variable not used can be represented by _.

As example of usage (from the official JEP:

static int count(Iterable<Order> orders) { 
    int total = 0; 
    for (Order _ : orders)    // Unnamed variable 
        total++; 
    return total; 
} 

In this case Order is required, but it is not used.

What are the advantages of this declaration? The goal is to allow the developers to communicate that a variable is not used and, probably, won't be used in the future.

Another interesting use of this feature is the use as parameter for functional interfaces:

Example:

@FunctionalInterface 
public interface FullNameCreator { 
   /** 
     * Creates a full name representation. 
     * 
     * @param firstName The first name 
     * @param lastName  The last name (family name) 
     * @return The combined full name 
     */ 
    String createFullName(String firstName, String lastName);  
} 

We create a @FunctionalInterface that composes a full name based on first name + last name.

A typical use case would be:

FullNameCreator simpleCreator = (first, last) -> first + " " + last; 
String fullName = simpleCreator.createFullName("Amy", "Smith");  
System.out.println(fullName); // Output: Amy Smith 

In Java 22 we can skip the second parameter with _:

FullNameCreator simpleCreator = (first, _) -> first; 
String fullName = simpleCreator.createFullName("Amy", "Smith");  
System.out.println(fullName); // Output: Amy 
 

JEP 463: Implicit classes (2. Preview) https://openjdk.org/jeps/463

The goal is to simplify the typical ceremonies of Java to be easier for new Java developers.

Here we have a typical HelloWorld class

public class HelloWorld { 
   public static void main(String[] args) { 
        System.out.println("Hello, World!"); 
    } 
} 

The objective is to have the same result with an implicit class:

void main() { 
    System.out.println("Hello, World!"); 
} 

There is more flexibility in the requirements for the call of a main method to start an application.


Fullstack Angular / Java application quick start guide.
WebApp built by Marco using SpringBoot 3.2.4 and Java 21. Hosted in Switzerland (GE8).