JEP-461: Stream Gatherers (Preview)
The number of intermediate operations available in the Stream API (e.g. filter, map, sorted, ...) is currently fixed and cannot be extended.

Since the introduction of streams in Java 8, which is now a whole 10 years ago, many suggestions have been made for further intermediate operations, each of which would make sense on its own, but all together would make the already large API too confusing.
Instead, the Stream API is made extensible by means of an extension point called "Stream Gatherers". For this purpose, the API receives the new intermediate operation "gather", which can be given its own implementations of the "Gatherer" interface or implementations provided by the Java API.
The following code shows the factory method for a simple gatherer that multiplies each element in the stream:
The use in the stream is as follows:
The result is a list that contains each element from the original stream three times (a, a, a, b, b, b, c, c, c).
A number of Gatherer implementations, such as windowFixed, windowSliding or fold, are available via the class Gatherers available.
The application of windowSliding looks something like this:
The issue:
JEP-447: Statements before super(...) (Preview)
Previously, calls to super(...) or this(...) in constructors always had to come first. This JEP makes it possible to place certain statements in front of these calls. However, there are restrictions for such statements, for example they may not contain any references to the instance to be created. Calls to static methods are therefore permitted, for example.
It is now possible to perform a validation before the super(...) call, as in the class shown above. Previously, the validation would either have been performed after the super call and unnecessary work would have been carried out in the event of an error; the alternative would be to wrap val in a validation method in the super call. In contrast, the code shown above is both efficient and easy to understand.
The same applies to this(...) calls, as the following example shows:
JEP-457: Class-File API (Preview)
In the Java ecosystem, parsing, generating and transforming class files is common practice, e.g. in tools or frameworks that dynamically analyze, modify or generate bytecode. They use class file libraries such as ASM, BCEL or Javassist for this purpose. The JDK itself also has its own class file library based on ASM.
New Java language functions and JVM properties lead to changes in the class file format. However, due to Java's semi-annual release cycle, the class format also changes frequently, making it difficult for the class file libraries and frameworks based on them to keep up with the changes.
With this JEP, the Java platform should define and implement a standard API for class files that evolves along with the format of the class files. Frameworks and tools that use this API can thus support the latest JDK version more quickly. Another goal is to get rid of the JDK's dependency on ASM.
As this blog post is primarily aimed at application developers who use the corresponding frameworks but do not develop them themselves, I will not provide any code examples here and refer you to the description and examples in the JEP-457.
JEP-463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
To make learning Java as easy as possible for beginners, the simplest Java program with this preview feature looks like this:
The first sense of achievement comes quickly and easily, without having to deal with concepts such as classes, static methods or method visibility.
The JVM proceeds as follows when selecting the method to be executed: If there is a main method with parameter String[] args, this is executed. If such a method does not exist, the main() method is executed without parameters, if available. Whether it is static or not is irrelevant.
JEP-464: Scoped Values (Second Preview)
Scoped Values are intended to be a lightweight replacement for ThreadLocal. ThreadLocals are used by web frameworks, for example, to store information about a user session when processing server requests within a thread. This approach can be problematic, particularly in the case of virtual threads, of which there can be very many in contrast to conventional threads. If each of the millions of virtual threads had its own copy, this would require a significant amount of memory.
Scoped values make it possible for multiple threads to share data such as user information.
First, a ScopedValue instance of type UserSession is instantiated in the WebFramework (line 3). The reference is static so that it can also be accessed from other parts of the code.
In the doRequest(...) method, the userSession is retrieved from the store (line 14). It is then passed to the where(...) method of ScopedValue (line 16), and then run(...) is called directly (line 17), where the processing is delegated to the service instance.
In the handle(...) method of the Service class, the user session can now be read from the ScopedValue instance via get() and used.
The user session set in where(...)(line 17) is only valid within the scope of the run(...) method. If an attempt were made in line 18 to access the previously set userSession via USER_SESSION.get(), the result would be a NoSuchElementException.
In addition, the set value cannot be reset within the scope, as ScopedValue does not have a set(...) method. This simplifies concurrent programming and also contributes to better performance.
JEP-459: String Templates (Second Preview)
Apart from a technical change in the types of template expressions, nothing has changed in the 2nd preview compared to the first.
Expressions are introduced with \{ and closed with }. STR is a StringTemplate-Processorwhich evaluates the expressions and inserts the result at the respective position in the string template.
Text blocks are also supported, for example to generate JSON or other multi-line strings:
It is very practical that double quotation marks in string templates do not have to be escaped. The result looks like this:
In addition to STR, there are also FMTa FormatProcessor that performs formatting based on the Formatter specification permitted:
However, simply parsing values in strings was not enough for the designers of the feature. When generating SQL statements, for example, there is a risk of SQL injection:
The value "Smith' OR p.last_name 'Smith" could be used to generate a statement that returns all of Person's entries. The TemplateProcessor mechanism in Java should therefore make it possible to provide different processors for different areas of application. It is therefore possible to write your own processors that produce valid or safe results. In the above case, for example, an SQL processor could escape the quotation marks in the expression values.
The result does not necessarily have to be of the string type; a processor that has an SQL query or JSON object as the result would therefore also be conceivable.
Here is an example of a self-written template processor that mirrors all values:
JEP-462: Structured Concurrency (Second Preview)
Structured Concurrency is derived from the following simple principle:
"When a task is split into concurrent subtasks, they all return to the same place, namely the task's code block."
This is not the case with the previous concurrency implemented using ExecutorService, for example.
This JEP is intended to create an approach to concurrent programming in which the natural relationship between tasks and subtasks is preserved, resulting in more readable, maintainable and reliable concurrent code. In Structured Concurrency, subtasks are processed as part of a task. The parent task waits for the results and monitors errors in the individual subtasks.
The two subtasks findUser() and fetchOrder() are processed here within a common scope. The join() statement in line 6 waits for the completion of all subtasks and then merges and returns the results.
The shutdown policy "ShutdownOnFailure" (line 2) causes the first occurrence of an exception in one of the subtasks to abort the other subtasks that are still running and the exception is propagated further. This policy is relevant if the results of all subtasks are required.
There is also the shutdown policy "ShutdownOnSuccess". This causes the result of the first successful subtask to be accepted and all other subtasks still running to be aborted. This policy is used if only the result of one of the subtasks is required:
In Java 22, Structured Concurrency is available for the second time as a preview feature, without any changes compared to the first preview, in order to collect further feedback from the community.
JEP-460: Vector API (Seventh Incubator)
With the Vector API, Java introduces cross-platform support for the development of data-parallel algorithms. Using a "Single Instruction Multiple Data" (SIMD) model, the vector instructions of different CPU architectures are to be supported. Computing operations (instructions) are executed on several values simultaneously in just one CPU cycle instead of just one value. Use cases for this include image and video processing.
Code example:
The Vector API is now included in the seventh Incubator version, with performance improvements and bug fixes compared to the previous version, as well as the extension that MemorySegments now supports arrays of all native data types instead of only arrays of type byte.



