To run each example use: java --enable-preview --source 21 <FileName.java>
- 430 - String Templates (Preview)
- 431 - Sequenced Collections
- 439 - Generational ZGC
- 440 - Record Patterns
- 441 - Pattern Matching for switch
- 442 - Foreign Function & Memory API (Third Preview)
- 443 - Unnamed Patterns and Variables (Preview)
- 444 - Virtual Threads
- 445 - Unnamed Classes and Instance Main Methods (Preview)
- 446 - Scoped Values (Preview)
- 448 - Vector API (Sixth Incubator)
- 449 - Deprecate the Windows 32-bit x86 Port for Removal
- 451 - Prepare to Disallow the Dynamic Loading of Agents
- 452 - Key Encapsulation Mechanism API
- 453 - Structured Concurrency (Preview)
- Virtual Threads
- notes about Virtual Threads
- promotion to standard
- changed to make virtual threads always support thread-local
- in preview releases was possible to create a virtual thread without thread-local support
- flag
jdk.traceVirtualThreadLocals
to show the strack trace when a virtual threads sets a value in thread-local variable - continuations:
- can be viewed as representation of the current state of the program
- used internally by the JVM to wrap the work by virtual threads
- there isn't a public API available, only internal
- possible uses:
- virtual threads
- coroutines
- generators
- Scoped Values
- promoted from incubated to preview feature
- minor change from JDK 19
- moved package from
jdk.incubator.concurrent
tojava.util.concurrent
- moved package from
- Structured Concurrency
- promoted from incubated to preview feature
- moved from pacote
jdk.incubator.concurrent
tojava.util.concurrent
- changes from JDK 19 and 20:
- changed method
StructuredTaskScope::fork
to return aSubtask
instanceof of aFuture
- the sealed interface
Subtask
extendsSupplier<T>
- the method
Subtask::get
behaves exaclty likeFuture::resultNow
- calling the method
Subtask::get
never blocks, it throws anIllegalStateException
when calling beforejoin
or when the subtask has not completed successfully
- changed method
- Record Patterns
- promotion to standard
- the main change is remove the support for record pattern in header of an enhanced for loop
- Pattern Matching for
switch
- promotion to standard
- main changes from last JEPs:
- removed parenthesized patterns (
case int i when (i > 0)
) - allow qualified enum constants as case constants (
case MyEnum.ITEM
) - exhaustiveness and compatibility:
- compiler will only require exhaustiveness if the
switch
uses any pattern,null
label or if selector expression isn't from a legacy type (char
,byte
,short
,int
,Character
,Byte
,Short
,Integer
,String
or a enum)
- compiler will only require exhaustiveness if the
- removed parenthesized patterns (
- improved switch to support pattern matching for types (like
instanceof
) - support for
null
case - support for guards where we can use a boolean expression (
case String s when s.length > 10
) - scope for pattern variable:
- the scope of pattern variable in visible only in the guard clause and the case body (expression, block or throw)
- fall through:
switch
with type pattern doesn't support falling through- if using case label with
:
, we must end the block withbreak
oryield
(case String s: ...; break;
,case String s: ...; yield s.length();
)
- String Templates
- improve the string with embedded expressions and template processors
- goals:
- simply the creation and expression of string with computed computed
- improve the security to work with strings provided by users with validations and transformations
- enable the cration of non-string values computed from literal text and embedded expressions without having to use a intermediate string representation
- string templates introduces the string interpolatins in Java and also provides a mechanism to validate/transform the string to avoid security issues
- template expressions are a new kind of expressions that performs string interpolation and also provides a way to programmatically validate or transform the interpolation result
String greetings = STR."Hello \{name}"
- template expression is composed by:
- a template processor (
STR
) - dot character (
.
) - template (
"My name is \{name}"
) which contains an embedded expresion (\{name}
)
- a template processor (
- the template literal can be defined with single or multi-line (using
"""
like text blocks)STR.""" Hello \{name} from multi-line template expression. """
- the template expressions is evaluated at run time, the template processor combines the literal text with the values of the embedded expressions to produce a result
- the result of the template processor is often a string, but it could be transform to any other value
- embedded expression
- an embedded expression can perform any Java expression (access variable, arithmetic operation, call method and fields, another template expression)
- the embedded expressions are evaluated from left to right
- double-quote character doesn't need to be escaped inside an embedded expression
STR."The file exists: \{file.exists() ? "yes" : "no"}"
- the embedded expression can be spread over multiples lines without introducing newlines
- the expression is interpolated in the same line from
\
character
String time = STR."The time is \{ DateTimeFormatter .ofPattern("HH:mm:ss") .format(LocalTime.now()) } right now"
- the expression is interpolated in the same line from
- template processors:
STR
template processor:STR
is a template processor provided by Java Platform, it performs the interpolation by replacing the embedded expressions with the stringified value of the expressionSTR
is a public static final fieldStringTemplate.STR
that is automatically imported into every Java source file
FMT
template processor:FMT
is another template processor provided by Java Platform, it behaves likeSTR
but allows value formatting like those inFormatter
- is a static final field of type
java.util.FormatProcessor
and must be explicity referenced withjava.util.FormatProcessor.FMT
- it uses the default locale
- we can create a custom template processor with another locale:
Locale locale = Locale.forLanguageTag("pt-BR"): FormatProcessor FMT_BR = FormatProcessor.create(locale); FMT_BR."Total: R$ %1.2f{42.42}";
- ex.:
StringTemplate.Processor.FMT."Total price: $%5.2f\{120.50}";
RAW
template processor:- is the standard template processor thar produces a unprocessed
StringTemplate
object - must be explicity referenced with
StringTemplate.RAW.""
- the
STR
template processor is just a lambda wrapper that callsRAW
and return theStringTemplate
processed- ex.:
StringTemplate st = StringTemplate.RAW."My name is \{"Neo"}"; String message = STR.process(st);
- is the standard template processor thar produces a unprocessed
- user-defined template processor:
- template processor is an object of the functional interface
StringTemplate.Processor
that receives aStringTemplate
and returns an object StringTemplate
has the following attributes:List<String> fragments
: list of the text fragments coming before and after the embedded expressionsList<Object> values
: list of the values produced by evaluating the embedded expressions in the order they appear
- to create a template processor we can just class that implements
StringTemplate.Processor
, a lambda expression or use static factory method:- ex:
// both are the same StringTemplate.Processor<String, RuntimeException> STR_NULL_SANITIZER = (StringTemplate st) -> { /* code */ }; // here we use `StringTemplate.Processor::of` so the `var` is inferred correctly to `StringTemplate.Processor<String, RuntimeException>` var STR_NULL_SANITIZER = StringTemplate.Processor.of((StringTemplate st) -> { var sb = new StringBuilder(); var fragments = st.fragments().iterator(); for (Object value : st.values()) { sb.append(fragments.next()); if (value == null) { sb.append("<NULL>"); } else { sb.append(value); } } sb.append(fragments.next()); return sb.toString(); });
- we can use normally:
- ex:
var message = STR_NULL_SANITIZER."Test: \{null}": // is equivalent to StringTemplate st = StringTemplate.RAW."Test: \{null}"; var message = STR_NULL_SANITIZER.process(st);
- template processor is an object of the functional interface
- Sequenced Collections
- new interfaces to define a common way to iterate throught sequenced collections (list, sets and maps)
- collections type hierarchy with new interfaces
- sequenced collection:
- a sequenced collection is a collection whose elements have a defined encounter order
- sequenced collection has a first and last elements, and the elements between them have successors and predecessors
- it supports common operations at the beginning and the end of the collection, also allow iterate it forward or backward
- methods from
SequencedCollection<E>
interface:reversed
addFirst
addLast
getFirst
getLast
removeFirst
removeLast
- sequenced set:
- sequenced set is a set that is sequenced collcetion that do not allow duplicate elements
- methods from
SequencedSet<E>
interface:reversed
- sequenced map:
- sequenced map is a map whose entries have a defined encounter order
- methods from
SequencedMap<K,V>
interface:reversed
sequencedKeySet
sequencedValues
sequencedEntrySet
putFirst
putLast
firstEntry
lastEntry
pollFirstEntry
pollLastEntry
- new methods in
Collections
:unmodifiableSequencedCollection
unmodifiableSequencedSet
unmodifiableSequencedMap
- Unnamed Classes and Instance Main Methods
- a.k.a. relaxed launch protocol
- facilitate the writing of first programm for students without needing to know another features designed for large programs
- unnamed class:
- any method declared in a source file without an enclosed class will be considered to be member of an unnamed top-level class
- the compiler requires an unnamed method to have a valid main method to be launched
- we cannot use javadoc tool to generate documation from a unnamed class (doesn't have a accessible API from other class)
- unnamed class is always final and cannot implement or extends any class other than
Object
- is equivalent to the following usage of anonymous class declaration:
new Object() { void main() {} }.main();
- as it doesn't have a name, so we can use its static methods like
ClassName.staticMethodName()
- it still will have the impliticy
this
reference - it can have:
- instance and static methods
- instance and static fields
- the default modifers are the same (package access and instance membership)
- the main difference is will only have an impliticy default zero-paramater constructor and cannot have initializers (static nor instance)
Class.isSynthetic
method returns true
- this JEPs introduces changes to how Java programs are launched:
- instance main method:
- the class must have a non-private zero-paramater constructor
- the main method doesn't need to be static, public nor have parameter
- example:
class HelloWord { void main() { System.out.println("Hello World!"); } }
- allowing unnamed class:
void main() { System.out.println("Hello World!"); }
- instance main method:
- order to select a main method (all must be non-private and it prioritize the methods in current class before the superclass):
static void main(String[])
static void main()
void main(String[])
void main()
- Unnamed Patterns and Variables
- goals:
- improve the readability of record patterns by ediling unnecessary nested patterns
- improve the maintanability of code by identifying variables that must be declared but will not be used
- unnamed pattern is denoted by
_
- it is a shorthand for the type pattern
var _
- it will facilitate the pattern matching where we are interested in the data types or structure
- unnamed variables:
- it never shadows another variable, can be used many times
- it can be used when:
- declaring a local variable (
int _ = q.remove()
) - resource specification of a try-with-resources (
try (var _ = ScopedContxt.acquire())
) - exception parameter in a catch clause (
catch (NumberFormatException _)
) - header of an enhanced for loop (
for (int i = 0; _ = sideEffect(); i++)
) - header of an enhanced for loop (
for (Order _ : orders)
) - lambda parameter (
(int x, int _) -> x + x
,_ -> "lambda with single parameter"
)
- declaring a local variable (
- unnamed patterns:
- unnamed pattern is an unconditional pattern which binds nothing
- we can use it in a nested position of a type pattern or a record pattern
p instanceof Point(_, int y)
case Point(int x, _)
p instanceof ColoredPoint(Point _, Color c)
- unnamed pattern variables:
- we can use it in any type pattern
p instanceof Point _
case Point _
- we can use it in any type pattern
- goals:
- Generational ZGC
- improve application performance by extending the Z Garbage Collection (ZGC) to maintain separate generations for young and old objects
- ZGC will be able to collect young objects more often
- possible gains:
- lower risk of allowcations stalls
- lower required heap memory overhead
- lower garbage collection CPU overhead
- JVM flags:
java -XX:+UseZGC -XX:+ZGenerational
- changes in
Thread
class:- improve
Thread::sleep(millis, nanos)
to actually perform sleep with sub-millisecond time - added method
Thread::sleep(Durantion)
,Thread::join(Durantion)
andThread::isVirtual
- improve
- added methos in
Future
that doesn't declare any checked exception (but will throw aIllegalStateException
if is not completed):T resultNow()
Throwable exceptionNow()
State state()
: returns the current state of the task (values:RUNNING
,SUCCESS
,FAILED
,CANCELLED
)
- added method
String::indexOf(String substr, int startIndex, int endIndex)
to find substring withing a index range - added method
StringBuilder::repeat(String str, int numberOfTimes)
to repeat a string # times - new methods to create collection with initial capacity:
HashMap::newHashMap(int)
HashSet::newHashSet(int)
LinkedHashMap::newLinkedHashMap(int)
LinkedHashSet::newLinkedHashSet(int)
- added method
InputStream::transferTo(OutputStream)
to read the stream and send to the received output stream java.net.http.Http Client
is nowAutoCloseable
and new methods were added to close/shutdown the connection pool.- classes
ExecutorService
andForkJoinPool
changed to implementAutoCloseable
- added methods to
Math
class:int ceilDiv(int, int)
long ceilDiv(long, int)
long ceilDiv(long, long)
int ceilDivExact(int, int)
long ceilDivExact(long, long)
int ceilMod(int, int)
long ceilMod(long, int)
long ceilMod(long, long)
- division that throws
ArithmeticException
in case of overflow:int divideExact(int, int)
long divideExact(long, long)
int floorDivExact(int, int)
long floorDivExact(long, long)
- methods to clamp a value in a range for each type
int
,long
,float
anddouble
:clamp(value, min, max)
- added method
BigInteger::parallelMultiply(BigInteger)
Deprecations:
Object::finalize
- constructors in
Integer
class:Integer(int)
andInteger(String)
- should use
Integer::valueOf(int)
andInteger::valueOf(String)
- should use
- The Arrival of Java 21
- JDK 21 JEPs
- JDK 21 Early Access Docs
- JEP 444: Virtual Threads Arrive in JDK 21, Ushering a New Era of Concurrency
- Upgrading from Java 17 to 21
- Java SE - Virtual Threads
- Presentations:
- JDK 21 Release Notes - Inside Java Newscast #55
- Java Virtual Threads - Oracle DevLive Level Up
- The Challenges of Indroducing Virtual Threads to the Java Platform
- Java 21 New Feature: Virtual Threads
- Java 21 API New Features
- Java 21 Brings Full Pattern Matching
- Java's Virtual Threads - Next Steps
- Continuations: The magic behind virtual threads in Java by Balkrishna Rawool @ Spring I/O 2024