codeWithYoha logo
Code with Yoha
Java

Java 21 Features with examples

Java 21 Features with examples
0 views
4 min read
#Java

Java 21, the latest long-term support (LTS) release, introduces several new features and enhancements aimed at improving developer productivity, performance, and security. This article will delve into some of the key features of Java 21, accompanied by examples to illustrate their usage.

1. Pattern Matching for Switch

Pattern matching for switch, introduced in earlier versions, is refined in Java 21. This feature allows for more expressive and concise code by enabling pattern matching directly in switch expressions and statements.

Example:

public class PatternMatchingSwitch {
    public static void main(String[] args) {
        Object obj = "Hello, Java 21!";

        String result = switch (obj) {
            case Integer i -> "Integer: " + i;
            case String s -> "String: " + s;
            case Double d -> "Double: " + d;
            default -> "Unknown type";
        };

        System.out.println(result);
    }
}

2. Sequenced Collections

Java 21 introduces SequencedCollection, a new interface that extends Collection and ensures a predictable iteration order. This feature simplifies working with collections where the sequence matters, such as lists and sets.

Example:

import java.util.*;

public class SequencedCollectionsExample {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>(List.of("Java", "Kotlin", "Scala"));
        SequencedCollection<String> sequencedList = new SequencedCollection<>(list);

        for (String language : sequencedList) {
            System.out.println(language);
        }
    }
}

3. Record Patterns

Record patterns simplify data extraction from record types, making code more concise and readable. This feature enhances pattern matching by allowing the deconstruction of record components directly within patterns.

Example:

public record Point(int x, int y) {}

public class RecordPatternExample {
    public static void main(String[] args) {
        Point point = new Point(10, 20);

        if (point instanceof Point(int x, int y)) {
            System.out.println("X: " + x + ", Y: " + y);
        }
    }
}

4. Virtual Threads

Virtual threads are a lightweight, high-performance alternative to traditional threads. They enable the creation of thousands of threads without significant overhead, making concurrent programming more efficient.

Example:

public class VirtualThreadsExample {
    public static void main(String[] args) {
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            List<Callable<String>> tasks = List.of(
                () -> "Task 1",
                () -> "Task 2",
                () -> "Task 3"
            );

            List<Future<String>> results = executor.invokeAll(tasks);

            for (Future<String> result : results) {
                System.out.println(result.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. Enhanced Generics

Java 21 introduces enhanced generics, allowing for more flexible and expressive type definitions. This feature improves code reuse and type safety.

Example:

import java.util.*;

public class EnhancedGenericsExample {
    public static void main(String[] args) {
        List<Pair<String, Integer>> pairs = List.of(
            new Pair<>("One", 1),
            new Pair<>("Two", 2),
            new Pair<>("Three", 3)
        );

        for (Pair<String, Integer> pair : pairs) {
            System.out.println(pair.getFirst() + ": " + pair.getSecond());
        }
    }
}

class Pair<F, S> {
    private final F first;
    private final S second;

    public Pair(F first, S second) {
        this.first = first;
        this.second = second;
    }

    public F getFirst() {
        return first;
    }

    public S getSecond() {
        return second;
    }
}

6. Improved Foreign Function & Memory API

The Foreign Function & Memory API has been improved, making it easier to interact with native code and memory. This feature provides a safer and more efficient way to handle native resources.

Example:

import java.foreign.*;
import java.foreign.memory.*;

public class ForeignFunctionExample {
    public static void main(String[] args) {
        MemorySegment memorySegment = MemorySegment.allocateNative(1024);
        try (ResourceScope scope = memorySegment.scope()) {
            MemoryAccess.setInt(memorySegment, 42);
            int value = MemoryAccess.getInt(memorySegment);
            System.out.println("Value: " + value);
        }
    }
}

7. Structured Concurrency

Structured concurrency simplifies the management of concurrent tasks by treating them as a single unit of work. This feature enhances readability and reliability in concurrent programming.

Example:

import java.util.concurrent.*;

public class StructuredConcurrencyExample {
    public static void main(String[] args) {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            Future<String> future1 = scope.fork(() -> "Task 1");
            Future<String> future2 = scope.fork(() -> "Task 2");

            scope.join();
            scope.throwIfFailed();

            System.out.println(future1.resultNow());
            System.out.println(future2.resultNow());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

8. String Templates

String templates simplify string formatting by allowing the embedding of expressions directly within string literals. This feature enhances readability and reduces the potential for errors.

Example:

public class StringTemplatesExample {
    public static void main(String[] args) {
        String name = "Java";
        int version = 21;

        String message = STR."Welcome to {name} {version}!";
        System.out.println(message);
    }
}

Conclusion

Java 21 introduces a range of powerful new features and enhancements, from pattern matching and virtual threads to enhanced generics and structured concurrency. These advancements are designed to improve developer productivity, performance, and code readability. By leveraging these new capabilities, developers can write more efficient, maintainable, and expressive Java code.

That's all for this tutorial, I hope you enjoyed it, and until our next tutorial, take care.
Thank you!