Java 21 major language and API improvements
Java 21 has been released in September 2023.
The following content is summarizing the most important changes to the Java API, the Java language, and the JVM introduced with Java 21.
For a more complete overview follow the links in the following sections referring to the official Oracle release documents.
Java 21 Language improvements
The following describes selected improvements of the Java language. See the Java 21 release notes. See Java Language Updates for Java SE 21.
With Java 21 the following language enhancements are now generally available
Java 21 is introducing the following language enhancements as developer preview.
JEP 430 is starting with String Templates as developer preview. String templates complement Java’s existing string literals and text blocks by coupling literal text with embedded expressions and template processors to produce specialized results.
JEP 443 is starting with Unnamed Patterns and Variables. Unnamed patterns, which match a record component without stating the component’s name or type, and unnamed variables, which can be initialized but not used. Both are denoted by an underscore character,
_
.JEP 445 is starting with Unnamed Classes and Instance Main Methods.
We are not diving into the details of these preview features and defer that until they are moving from preview for general availability.
Record
record Point(int x, int y) {
}
var point = new Point(3, 4);
if (point instanceof Point(var x, var y)) {
var length = Math.sqrt(2 * (x + y));
}
interface Part {
}
record Circle(int radius) implements Part {
}
record Square(int length) implements Part {
}
Part part = new Square(4);
double perimeter = switch (part) {
case Square(var length) -> 4 * length;
case Circle(var radius) -> 2 * radius * Math.PI;
case null, default -> throw new IllegalStateException("Unexpected value: " + part);
};
Record patterns with switch support many more additional features like when clauses. Read more on the Java 21 language document for Pattern Matching for switch Expressions and Statements.
Java 21 API improvements
The following describes selected improvements of the Java API. See the Java 21 release notes.
Java 21 is introducing the following API/library enhancements.
JEP 444 Virtual threads are lightweight threads that dramatically reduce the effort of writing, maintaining, and observing high-throughput concurrent applications.
JEP 431 Sequenced Collections Introduce new interfaces to represent collections with a defined encounter order. Each such collection has a well-defined first element, second element, and so forth, up to the last element. It also provides uniform APIs for accessing its first and last elements, and for processing its elements in reverse order.
Java 21 is introducing the following API enhancements as developer preview or Incubator.
JEP 446 is continuing with scoped values, which enable the sharing of immutable data within and across threads. They are preferred to thread-local variables, especially when using large numbers of virtual threads
JEP 453 is continuing with simplifying multithreaded programming by introducing an API for structured concurrency. Structured concurrency treats multiple tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability..
We are not diving into the details of these preview features and defer that until they are moving from preview for general availability.
Sequenced Collection Api
List<String> list = new ArrayList<>();
list.addFirst("Java 21 LTS");
list.addLast("rocks!");
SequencedCollection<String> reversed = list.reversed();
Assertions.assertEquals("rocks!", reversed.getFirst());
Collection implementations with items in defined order hat a rather inconsistent API.
Those collection types now implement SequencedCollection
offering methods for accessing head and tail elements and reversing the ordering.
Set types that are maintaining a sequence have their own interface SequencedSet
sub-type.

SequencedMap<String, String> map = new LinkedHashMap<>(2);
map.putFirst("first", "Java 21 LTS");
map.putLast("last", "rocks!");
SequencedCollection<String> reversed = map.sequencedValues().reversed();
Assertions.assertEquals("rocks!", reversed.getFirst());
Map
types that are maintaining a sequence are based on SequencedMap
Virtual Threads
Like platform threads, a virtual thread is also an instance of java.lang.Thread
class, but does not allocate a specific OS thread and consumes much less OS resources.
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
For frameworks that are managing multi-threading it’s usually just a matter of the proper configuration to switch from platform threads to virtual threads.
Spring Boot for example just requires spring.threads.virtual.enabled=true
in the application configuration.