You are currently viewing Java 21 New Features

Java 21 New Features

1. Introduction

Java 21 is a Long-Term Support (LTS) version of Java that was officially released on September 19, 2023. The Java Specification Request(JSR) 396 provides a detailed view of the enhancements in this new version of Java. In this tutorial, you will learn the main features of the JDK 21. We will not cover any preview feature in this article.

2. Record Patterns

Java 17 introduced the Record type as a way to simplify the implementation of data-carrier classes. Any code using a Record class can use the automatically generated accessors to retrieve the field values.

//Use of record before Java 21
        if(object instanceof Student student){
            String firstName = student.firstName();
            String lastName = student.lastName();
            System.out.println(firstName +" " +lastName);
        }

Java 21 has provided an enhancement to the previous code. The compiler uses pattern matching to automatically bind the record components to variables.

//Use of record with Java 21
        if(object instanceof Student(String firstName, String lastName)){
            System.out.println(firstName +" " +lastName);
        }

Read more about Record Patterns(JEP 440).

3. Pattern Matching for switch

Prior to this version, the switch construct only allowed a limited number of Java types in a case label(integral primitive types, enum, String). In Java 21, you can use complex patterns in switch labels.

//Prior to Java 21
    private void switchBeforeJava21(Object object){
        if(object == null) {
            System.out.println("I'm null");
        }else if(object instanceof Integer i){
            if(i % 2 == 0)
                System.out.println("I'm even");
            else
                System.out.println("I'm odd");
        }else if(object instanceof String s){
            System.out.println("I'm a String : "+s);
        }else{
            System.out.println("I'm a different object");
        }
    }
//With Java 21
    private void switchWithJava21(Object object){
        switch (object){
            case null -> System.out.println("I'm null");
            case Integer i when i%2 == 0 -> System.out.println("I'm even");
            case Integer i when i%2 == 1 -> System.out.println("I'm odd");
            case String s -> System.out.println("I'm a String : "+s);
            default -> System.out.println("I'm a different object");
        }
    }

Read more about Pattern Matching for Switch (JEP 441).

4. Sequenced Collections

Java 21 has introduced three new interfaces SequencedCollection, SequencedSet, and SequencedMap. A SequencedCollection is a collection whose elements have a predefined encounter order. Thus, the collection has a first and last element. Each element in the collection has a predecessor and a successor. The collection also supports operations at each end (first and last element). A SequencedSet is a SequencedCollection that does not support duplicates. A SequencedMap is a Map whose entries have a predefined encounter order.

Sequenced Collections

4.1. Sequenced List

Java has updated the List hierarchy. The List interface extends SequencedCollection. Hence, a List is by default a SequencedCollection.

    private void sequencedList(){
        System.out.println("*****Sequenced List*****");
        List<String> list = new ArrayList<>();
        list.add("Hello");
        list.add("World");
        String firstItem = list.getFirst();
        String lastItem = list.getLast();
        List<String> reversedList = list.reversed();
        System.out.println(firstItem); //Hello
        System.out.println(lastItem);  // World
        System.out.println(reversedList); //[World, Hello]
    }

4.2. Sequenced Set

Unlike lists, not all sets are sequenced sets. Therefore, you cannot use the Set interface directly to create a SequencedSet.

    private void sequencedSet(){
        System.out.println("*****Sequenced Set*****");
        SequencedSet<String> set = new LinkedHashSet<>();
        set.add("Hello");
        set.add("World");
        String firstItem = set.getFirst();
        String lastItem = set.getLast();
        SequencedSet<String> reversedSet = set.reversed();
        System.out.println(firstItem);  //Hello
        System.out.println(lastItem);  // World
        System.out.println(reversedSet); //[World, Hello]
    }

4.3. Sequenced Map

Just like sets, not all maps are sequenced maps. HashMap is not a sequenced map, LinkedHashMap on the contrary, it is.

    private void sequencedMap(){
        System.out.println("*****Sequenced Map*****");
        SequencedMap<String,String> map = new LinkedHashMap<>();
        map.put("Hello","Hello");
        map.put("World","World");
        Map.Entry<String,String> firstItem = map.firstEntry();
        Map.Entry<String,String> lastItem = map.lastEntry();
        SequencedMap<String,String> reversedMap = map.reversed();
        System.out.println(firstItem);  //Hello=Hello
        System.out.println(lastItem);  //World=World
        System.out.println(reversedMap);  //{World=World, Hello=Hello}
    }

Read more about Sequenced Collections(JEP 431).

5. Virtual Threads

Java 21 introduces virtual threads, a lightweight thread type that simplifies writing and maintaining high-throughput applications. While it requires around 1Mb to create a traditional thread(or platform thread), a virtual thread only requires around 1Kb of memory.
The Thread class is enriched with new methods:

        Thread thread = Thread.ofVirtual().start(() -> {
            System.out.println("Hello from a virtual thread!");
        });

        System.out.println(thread.isVirtual());//True

You can also use the ExecutorService to create a large number of virtual threads:

        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            IntStream.range(0, 1_000_000).forEach(i ->
                    executor.submit(() -> {
                        // Simulate a task
                        System.out.println("Task " + i + " running");
                    })
            );
        }

Important: Please note that virtual threads are not meant to replace platform threads. Their goal is to provide a way to easily scale high-throughput applications.

Read more about Virtual Threads(JEP 444).

6. Key Encapsulation Mechanism API

The Key Encapsulation Mechanism(KEM) API is a new feature of Java 21, designed to help developers build post-quantum cryptographic protocols efficiently. The goal of KEM API is to strengthen the exchange of the symmetric encryption key in the context of Public Key Infrastructure (PKI). A new class javax.crypto.KEM is introduced to handle the encapsulation and decapsulation processes.

        // Receiver side
        KeyPairGenerator g = KeyPairGenerator.getInstance("X25519");
        KeyPair kp = g.generateKeyPair();
        publishKey(kp.getPublic());

        // Sender side
        KEM kemServer = KEM.getInstance("DHKEM");
        PublicKey publicKeyReceiver = retrieveKey();
        KEM.Encapsulator e = kemServer.newEncapsulator(publicKeyReceiver);
        KEM.Encapsulated enc = e.encapsulate();
        SecretKey sharedSecretSender = enc.key();
        byte[] keyEncapsulationMessage = enc.encapsulation();
        //...The key encapsulation message should be sent to the receiver here
        // using for example a method like sendBytes(keyEncapsulationMessage)

        // Receiver side
        // ...The receiver should receive the key encapsulation message  here
        // using for example a method like receiveBytes()
        byte[] em = keyEncapsulationMessage;
        KEM kemR = KEM.getInstance("DHKEM");
        KEM.Decapsulator d = kemR.newDecapsulator(kp.getPrivate());
        SecretKey sharedSecretReceiver = d.decapsulate(em);

        // sharedSecretSender and sharedSecretReceiver will be identical
        assert Arrays.equals(sharedSecretSender.getEncoded(),sharedSecretReceiver.getEncoded());

Read more about Key Encapsulation Mechanism API(JEP 452).

7. Conclusion

In this article, you learned the main features introduced by Java 21.
You can find the complete code of this article here in GitHub

Noel Kamphoa

Experienced software engineer with expertise in Telecom, Payroll, and Banking. Now Senior Software Engineer at Societe Generale Paris.