Skip to content

Instantly share code, notes, and snippets.

@RajaniCode
Created October 31, 2024 21:44
Show Gist options
  • Select an option

  • Save RajaniCode/0d3f31135512222bbb5a3ec59aa942f5 to your computer and use it in GitHub Desktop.

Select an option

Save RajaniCode/0d3f31135512222bbb5a3ec59aa942f5 to your computer and use it in GitHub Desktop.
Java22.java
// Java 22
// OpenJDK 22
// % export PATH="$HOME/Downloads/Software/OpenJDK/JDK22.0.2/jdk-22.0.2.jdk/Contents/Home/bin/":$PATH
// % java --enable-preview --source 22 --enable-native-access=ALL-UNNAMED --add-modules=jdk.incubator.vector Java22.java
// Or
// % javac -Xlint:preview --enable-preview --source 22 --add-modules=jdk.incubator.vector Java22.java
// % java --enable-preview --enable-native-access=ALL-UNNAMED --add-modules=jdk.incubator.vector Java22
// % rm -rf *.class
// Java 21
// OpenJDK 21
// % export PATH="$HOME/Downloads/Software/OpenJDK/JDK21.0.2/jdk-21.0.2.jdk/Contents/Home/bin/":$PATH
// % java --enable-preview --source 21 --enable-native-access=ALL-UNNAMED --add-modules=jdk.incubator.vector Java22.java
// Or
// % javac -Xlint:preview --enable-preview --source 21 --add-modules=jdk.incubator.vector Java22.java
// % java --enable-preview --enable-native-access=ALL-UNNAMED --add-modules=jdk.incubator.vector Java22
// % rm -rf *.class
/*
# 1 # 423: Region Pinning for G1
# 2 # 447: Statements before super(...) (Preview)
# 3 # 454: Foreign Function & Memory API
# 4 # 456: Unnamed Variables & Patterns
# 5 # 457: Class-File API (Preview)
# 6 # 458: Launch Multi-File Source-Code Programs
# 7 # 459: String Templates (Second Preview)
# 8 # 460: Vector API (Seventh Incubator)
# 9 # 461: Stream Gatherers (Preview)
# 10 # 462: Structured Concurrency (Second Preview)
# 11 # 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
# 12 # 464: Scoped Values (Second Preview)
*/
import static java.lang.StringTemplate.RAW;
// import static java.lang.StringTemplate.STR;
import static java.util.FormatProcessor.FMT;
import java.io.IOException;
import java.lang.classfile.ClassFile;
import java.lang.constant.ClassDesc;
import java.lang.constant.MethodTypeDesc;
import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SymbolLookup;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.StringTemplate.Processor;
import java.nio.file.Path;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.time.Duration;
import java.time.format.DateTimeFormatter;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.StructuredTaskScope;
import java.util.concurrent.StructuredTaskScope.Subtask;
import java.util.concurrent.ThreadLocalRandom;
import java.util.FormatProcessor;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Supplier;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Queue;
import java.util.Random;
import java.util.ResourceBundle;
import java.util.stream.Collectors;
import java.util.stream.Gatherer;
import java.util.stream.Gatherers;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.UUID;
import jdk.incubator.vector.FloatVector;
import jdk.incubator.vector.VectorSpecies;
// # 11 # 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
// Java 21 Preview
// class Java21 {
// Java 22 Preview
void main() {
// public static void main(String[] args) {
SystemProperties propertiesSystem = new SystemProperties();
propertiesSystem.print();
System.out.println();
// # 1 # 423: Region Pinning for G1
System.out.println("# 1 # 423: Region Pinning for G1");
System.out.print("""
Reduce latency by implementing region pinning in G1, so that garbage collection need not be disabled during Java Native Interface (JNI) critical regions.
Pinning regions during minor collection operations.
Maintain a count of the number of critical objects in each region:
Increment it when a critical object in that region is obtained, and decrement it when that object is released.
When the count is zero then garbage-collect the region normally; when the count is non-zero, consider the region to be pinned.
During a major collection, do not evacuate any pinned region.
During a minor collection, treat pinned regions in the young generation as having failed evacuation, thus promoting them to the old generation. Do not evacuate existing pinned regions in the old generation.
""");
System.out.println();
// # 2 # 447: Statements before super(...) (Preview)
var previewStatementsBeforeSuper = new StatementsBeforeSuperPreview();
previewStatementsBeforeSuper.print();
System.out.println();
// # 3 # 454: Foreign Function & Memory API
var apiForeignFunctionAndMemory = new ForeignFunctionAndMemoryAPI();
apiForeignFunctionAndMemory.print();
System.out.println();
// # 4 # 456: Unnamed Variables & Patterns
var variablesAndPatternsUnnamed = new UnnamedVariablesAndPatterns();
variablesAndPatternsUnnamed.print();
System.out.println();
// # 5 # 457: Class-File API (Preview)
var previewClassFileAPI = new ClassFileAPIPreview();
previewClassFileAPI.print();
System.out.println();
// # 6 # 458: Launch Multi-File Source-Code Programs
var programsLaunchMultiFileSourceCode = new LaunchMultiFileSourceCodePrograms();
programsLaunchMultiFileSourceCode.print();
System.out.println();
// # 7 # 459: String Templates (Second Preview)
var secondPreviewStringTemplates = new StringTemplatesSecondPreview();
secondPreviewStringTemplates.print();
System.out.println();
// # 8 # 460: Vector API (Seventh Incubator)
var seventhIncubatorVectorAPI = new VectorAPISeventhIncubator();
seventhIncubatorVectorAPI.print();
System.out.println();
// # 9 # 461: Stream Gatherers (Preview)
var previewStreamGatherers = new StreamGatherersPreview();
previewStreamGatherers.print();
System.out.println();
// # 10 # 462: Structured Concurrency (Second Preview)
var secondPreviewStructuredConcurrency = new StructuredConcurrencySecondPreview();
secondPreviewStructuredConcurrency.print();
System.out.println();
// # 11 # 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
System.out.println("# 11 # 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)");
System.out.print("""
Allow the main method of a launched class to have public, protected, or default (i.e., package) access.
If the launched class contains a main method with a String[] parameter then choose that method.
Otherwise, if the class contains a main method with no parameters then choose that method.
In either case, if the chosen method is static then simply invoke it.
Otherwise, the chosen method is an instance method and the launched class must have a zero-parameter, non-private constructor (i.e., of public, protected, or package access). Invoke that constructor and then invoke the main method of the resulting object.
If there is no such constructor then report an error and terminate.
If there is no suitable main method then report an error and terminate
""");
System.out.println();
// # 12 # 464: Scoped Values (Second Preview)
var secondPreviewScopedValues = new ScopedValuesSecondPreview();
secondPreviewScopedValues.print();
}
// }
class A {
int i;
A() {
// Java 22 Preview // error: cannot reference this before supertype constructor has been called // 3 errors
// Pre-Java 22 Preview // error: call to super must be first statement in constructor // 1 error
// this.i++; // Error
// this.hashCode(); // Error
// System.out.print(this); // Error
super();
}
}
class B {
int b;
class C {
int c;
C() {
// Java 22 Preview // no error
// Pre-Java 22 Preview // error: call to super must be first statement in constructor // 1 error
B.this.b++; // Allowed - enclosing instance // Java 22 Preview
// Java 22 Preview // error: cannot reference this before supertype constructor has been called
// Pre-Java 22 Preview // error: call to super must be first statement in constructor
// C.this.c++; // Error - same instance
super();
}
}
}
class D {
int i;
}
class E extends D {
E() {
// Java 22 Preview // error: cannot reference super before supertype constructor has been called
// Pre-Java 22 Preview // error: call to super must be first statement in constructor
// super.i++; // Error
super();
}
}
class F {
int i;
F() {
// Java 22 Preview // error: cannot reference this before supertype constructor has been called // 2 errors
// Pre-Java 22 Preview // error: call to super must be first statement in constructor // 1 error
// i++; // Error
// hashCode(); // Error
super();
}
}
class Outer {
void hello() {
System.out.println("Hello");
}
class Inner {
Inner() {
// Java 22 Preview // no error
// Pre-Java 22 Preview // error: call to super must be first statement in constructor // 1 error
hello(); // Allowed - enclosing instance method // Java 22 Preview
super();
}
}
}
class Out {
class In { }
Out() {
// Java 22 Preview // error: cannot reference super before supertype constructor has been called
// Pre-Java 22 Preview // error: call to super must be first statement in constructor
// new In(); // Error - 'this' is enclosing instance
super();
}
}
class O {
class V { }
class U {
U() {
// Java 22 Preview // no error
// Pre-Java 22 Preview // error: call to super must be first statement in constructor
var tmp = new V() { }; // Allowed // Java 22 Preview
super();
}
}
}
class X {
X() { }
X(Object instance) { }
}
class W<T> extends X {
W() {
// Java 22 Preview // error: cannot reference this before supertype constructor has been called
// Pre-Java 22 Preview // error: cannot reference this before supertype constructor has been called
// super(this); // Error - refers to 'this'
}
@SuppressWarnings({ "unchecked" })
W(List<?> list) {
// Java 22 Preview // no error
// Pre-Java 22 Preview // no error
super((T)list.get(0)); // Allowed - refers to 'T' but not 'this' // Java 22 Preview // Pre-Java 22 Preview // warning: [unchecked] unchecked cast
}
}
class StatementsBeforeSuperPreview {
public void print() {
System.out.println("# 2 # 447: Statements before super(...) (Preview)");
System.out.println("Java 22 Preview error: cannot reference super/this before supertype constructor has been called");
System.out.println("Pre-Java 22 Preview error: call to super must be first statement in constructor");
System.out.println("Pre-Java 22 Preview error: cannot reference this before supertype constructor has been called");
}
}
class ForeignFunctionAndMemoryAPI {
private void radixsort() {
// 1. Find foreign function on the C library path
Linker linkerNative = Linker.nativeLinker();
SymbolLookup lookuppSymbol = linkerNative.defaultLookup();
MethodHandle radixsortHandle = linkerNative.downcallHandle(
lookuppSymbol.find("radixsort").orElseThrow(),
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_CHAR));
// 2. Allocate on-heap memory to store four strings
String[] javaStrings = { "Delta", "Gamma", "Alpha", "Beta" };
System.out.println("radixsort input: " + Arrays.toString(javaStrings));
// Java 22
// 3. Use try-with-resources to manage the lifetime of off-heap memory
try (Arena offHeap = Arena.ofConfined()) {
// Java 22
// 4. Allocate a region of off-heap memory to store four pointers
MemorySegment pointers = offHeap.allocate(ValueLayout.ADDRESS, javaStrings.length);
// 5. Copy the strings from on-heap to off-heap
for (int i = 0; i < javaStrings.length; i++) {
// Java 22
MemorySegment cString = offHeap.allocateFrom(javaStrings[i]);
pointers.setAtIndex(ValueLayout.ADDRESS, i, cString);
}
// 6. Sort the off-heap data by calling the foreign function
// invoke // unreported exception Throwable; must be caught or declared to be thrown
try {
radixsortHandle.invoke(pointers, javaStrings.length, MemorySegment.NULL, '\0');
} catch (Throwable ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
// 7. Copy the (reordered) strings from off-heap to on-heap
for (int i = 0; i < javaStrings.length; i++) {
MemorySegment cString = pointers.getAtIndex(ValueLayout.ADDRESS, i);
// Java 22
javaStrings[i] = cString.reinterpret(Long.MAX_VALUE).getString(0);
}
}
// 8. All off-heap memory is deallocated here
System.out.println("radixsort output: " + Arrays.toString(javaStrings));
}
private void strlen(String text) {
System.out.println("strlen input: " + text);
try (Arena arena = Arena.ofConfined()) {
// Java 22
// Allocate off-heap memory and
// copy the argument, a Java string, into off-heap memory
MemorySegment segmentMemory = arena.allocateFrom(text);
// Link and call the C function strlen
// Obtain an instance of the native linker
Linker linkerNative = Linker.nativeLinker();
// Locate the address of the C function signature
SymbolLookup lookupSymbol = linkerNative.defaultLookup();
MemorySegment segmentMemoryLookup = lookupSymbol.find("strlen").get();
// Create a description of the C function
FunctionDescriptor descriptorFunction =
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS);
// Create a downcall handle for the C function
MethodHandle strlenHandle = linkerNative.downcallHandle(segmentMemoryLookup, descriptorFunction);
try {
// Call the C function directly from Java
// invokeExact // unreported exception Throwable; must be caught or declared to be thrown
System.out.println("strlen output: " + (long)strlenHandle.invokeExact(segmentMemory));
} catch (Throwable ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
}
}
class Qsort {
static int qsortCompare(MemorySegment elem1, MemorySegment elem2) {
return Integer.compare(elem1.get(ValueLayout.JAVA_INT, 0), elem2.get(ValueLayout.JAVA_INT, 0));
}
}
// Obtain instance of native linker
private final Linker nativeLinker = Linker.nativeLinker();
private void qsort(int... unsortedArray) throws Throwable {
System.out.println("qsort input: " + Arrays.toString(unsortedArray));
int[] sorted = null;
// Create downcall handle for qsort
MethodHandle qsortHandle = nativeLinker.downcallHandle(
nativeLinker.defaultLookup().find("qsort").get(),
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS,
ValueLayout.JAVA_LONG,
ValueLayout.JAVA_LONG,
ValueLayout.ADDRESS));
// Create method handle for qsortCompare
// findStatic // unreported exception NoSuchMethodException; must be caught or declared to be thrown
// findStatic // unreported exception IllegalAccessException; must be caught or declared to be thrown
MethodHandle comparHandle = MethodHandles.lookup()
.findStatic(Qsort.class,
"qsortCompare",
MethodType.methodType(int.class,
MemorySegment.class,
MemorySegment.class));
// Create a Java description of a C function implemented by a Java method
FunctionDescriptor qsortCompareDesc = FunctionDescriptor.of(
ValueLayout.JAVA_INT,
ValueLayout.ADDRESS.withTargetLayout(ValueLayout.JAVA_INT),
ValueLayout.ADDRESS.withTargetLayout(ValueLayout.JAVA_INT));
// Create function pointer for qsortCompare
MemorySegment compareFunc = nativeLinker.upcallStub(comparHandle,
qsortCompareDesc,
Arena.ofAuto());
// Java 22
try (Arena arena = Arena.ofConfined()) {
// Allocate off-heap memory and store unsortedArray in it
MemorySegment array = arena.allocateFrom(ValueLayout.JAVA_INT,
unsortedArray);
// Call qsort
// invoke // unreported exception Throwable; must be caught or declared to be thrown
qsortHandle.invoke(array,
(long)unsortedArray.length,
ValueLayout.JAVA_INT.byteSize(),
compareFunc);
// Access off-heap memory
sorted = array.toArray(ValueLayout.JAVA_INT);
}
System.out.println("qsort output: " + Arrays.toString(sorted));
}
public void print() {
System.out.println("# 3 # 454: Foreign Function & Memory API");
radixsort();
strlen("Hola!");
try {
// unreported exception Throwable; must be caught or declared to be thrown
qsort(5, 7, 9, 3, 4, 6, 1, 8, 2, 0);
} catch (Throwable ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
}
}
record PointUnnamed(int x, int y) { }
enum ColorUnnamed{ RED, GREEN, BLUE }
record ColoredPointUnnamed(PointUnnamed p, ColorUnnamed c) { }
sealed abstract class Ball permits RedBall, BlueBall, GreenBall { }
final class RedBall extends Ball { }
final class BlueBall extends Ball { }
final class GreenBall extends Ball { }
record BoxBall<T extends Ball>(T content) { }
class UnnamedVariablesAndPatterns {
public void print() {
System.out.println("# 4 # 456: Unnamed Variables & Patterns");
System.out.println("Unnamed variables");
System.out.print("""
The following kinds of declarations can introduce either a named variable (denoted by an identifier) or an unnamed variable (denoted by an underscore):
A local variable declaration statement in a block,
A resource specification of a try-with-resources statement,
The header of a basic for statement,
The header of an enhanced for loop,
An exception parameter of a catch block, and
A formal parameter of a lambda expression.
""");
String _ = "A local variable declaration statement in a block";
String preview = "Java 21 Preview";
try {
int i = Integer.parseInt(preview);
} catch (NumberFormatException _) {
System.out.println("NumberFormatException: " + preview);
}
int[] numbers = new int[5];
for (int i = 0, _ = Thread.currentThread().activeCount(); i < 5; i++) { numbers[i] = i; }
int number = 0;
for (int _ : numbers) {
number =+ new Random().nextInt(50, 101);
}
System.out.println("Sum of 5 random numbers: " + number);
String[] lambda = { "Alpha", "Beta", null, "Gamma", "", null, "Delta", "", "Epsilon", "Gamma"};
System.out.println(Arrays.stream(lambda).filter(Objects::nonNull).distinct().collect(Collectors.toMap(String::toLowerCase, _ -> "lowercase")));
System.out.println("Unnamed pattern variables");
System.out.println("An unnamed pattern variable can appear in a type pattern, including var type patterns, regardless of whether the type pattern appears at the top level or is nested in a record pattern.");
System.out.println("By allowing us to elide names, unnamed pattern variables make run-time data exploration based on type patterns visually clearer, both in switch blocks and with the instanceof operator.");
System.out.println("Multiple patterns in case labels");
System.out.print("""
Currently, case labels are restricted to contain at most one pattern.
With the introduction of unnamed pattern variables and unnamed patterns, it is more likely that we will have within a single switch block several case clauses with different patterns but the same right-hand side.
""");
BoxBall<Ball> bo = new BoxBall<>(new GreenBall());
switch (bo) {
case BoxBall(RedBall _), BoxBall(BlueBall _) -> System.out.println("RedBall, BlueBall");
case BoxBall(GreenBall _) -> System.out.println("Green Ball");
case BoxBall(_) -> System.out.println("_");
}
System.out.print("""
A case label with multiple patterns can have a guard.
A guard governs the case as a whole, rather than the individual patterns.
""");
int numeral = 777;
bo = new BoxBall<>(new BlueBall());
switch (bo) {
case BoxBall(RedBall _), BoxBall(BlueBall _) when numeral == 777 -> System.out.println("RedBall, BlueBall, numeral = " + numeral);
case BoxBall(RedBall _), BoxBall(BlueBall _) -> System.out.println("RedBall, BlueBall");
case BoxBall(GreenBall _) -> System.out.println("Green Ball");
case BoxBall(_) -> System.out.println("_");
}
System.out.println("Pairing a guard with each pattern is not allowed, so this is prohibited");
// error: : or -> expected
/*
switch (bo) {
case BoxBall(RedBall _) when numeral == 0, BoxBall(BlueBall _) when numeral == 777 -> System.out.println("RedBall, BlueBall, numeral = " + numeral);
case BoxBall(RedBall _), BoxBall(BlueBall _) -> System.out.println("RedBall, BlueBall");
case BoxBall(GreenBall _) -> System.out.println("Green Ball");
case BoxBall(_) -> System.out.println("_");
}
*/
System.out.println("The unnamed pattern");
System.out.print("""
The unnamed pattern is an unconditional pattern that matches anything but declares and initializes nothing.
Like the unnamed type pattern var _ , the unnamed pattern can be nested in a record pattern.
It cannot, however, be used as a top-level pattern in, e.g., an instanceof expression or a case label.
""");
Object unnamedPoint = new PointUnnamed(1, 2);
if (unnamedPoint instanceof PointUnnamed _) {
System.out.println("The object is a PointUnnamed");
}
if (unnamedPoint instanceof PointUnnamed(int x, int _)) {
System.out.println("The object is a PointUnnamed, x = " + x);
}
if (unnamedPoint instanceof PointUnnamed(int x, _)) {
System.out.println("The object is a PointUnnamed, x = " + x);
}
ColoredPointUnnamed unnamedColoredPoint = new ColoredPointUnnamed(new PointUnnamed(1, 2), ColorUnnamed.BLUE);
if (unnamedColoredPoint instanceof ColoredPointUnnamed(PointUnnamed(int x, int y), _)) {
System.out.println("The object is ColoredPointUnnameds, x = " + x + ", y = " + y);
}
if (unnamedColoredPoint instanceof ColoredPointUnnamed(_, ColorUnnamed c)) {
System.out.println("The object is ColoredPointUnnamed, c = " + c);
}
if (unnamedColoredPoint instanceof ColoredPointUnnamed(PointUnnamed(int x, _), _)) {
System.out.println("The object is ColoredPointUnnameds, x = " + x);
}
if (unnamedColoredPoint instanceof ColoredPointUnnamed(PointUnnamed(int x, _), ColorUnnamed c)) {
System.out.println("The object is ColoredPointUnnamed x = " + x + ", c = " + c);
}
}
}
class ClassFileAPIPreview {
public void print() {
System.out.println("# 5 # 457: Class-File API (Preview)");
String javaVersion = String.format("Java Version: %s", System.getProperty("java.version"));
// % java Program
try {
ClassFile.of().buildTo(Path.of("Program.class"), ClassDesc.of("Program"), classBuilder -> classBuilder
.withMethodBody("main", MethodTypeDesc.ofDescriptor("([Ljava/lang/String;)V"), ClassFile.ACC_PUBLIC + ClassFile.ACC_STATIC,
codeBuilder -> codeBuilder
.getstatic(ClassDesc.of("java.lang.System"), "out", ClassDesc.of("java.io.PrintStream"))
.ldc(javaVersion)
.invokevirtual(ClassDesc.of("java.io.PrintStream"), "println", MethodTypeDesc.ofDescriptor("(Ljava/lang/Object;)V"))
.return_()));
System.out.println("Program.class created successfully, run java Program in the console to get the output of Java Version ");
} catch (IOException ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
}
}
class LaunchMultiFileSourceCodePrograms {
public void print() {
System.out.println("# 6 # 458: Launch Multi-File Source-Code Programs");
SourceCodeProgram.printStatic();
var programSourceCode = new SourceCodeProgram();
programSourceCode.printInstance();
}
}
record Rectangle(String name, double width, double height) {
double area() {
return width * height;
}
}
// Safely composing and executing database queries using StringTemplate.Processor
record QueryBuilder(Connection conn)
implements StringTemplate.Processor<PreparedStatement, SQLException> {
public PreparedStatement process(StringTemplate st) throws SQLException {
// 1. Replace StringTemplate placeholders with PreparedStatement placeholders
String query = String.join("?", st.fragments());
// 2. Create the PreparedStatement on the connection
PreparedStatement ps = conn.prepareStatement(query);
// 3. Set parameters of the PreparedStatement
int index = 1;
for (Object value : st.values()) {
switch (value) {
case Integer i -> ps.setInt(index++, i);
case Float f -> ps.setFloat(index++, f);
case Double d -> ps.setDouble(index++, d);
case Boolean b -> ps.setBoolean(index++, b);
default -> ps.setString(index++, String.valueOf(value));
}
}
return ps;
}
}
// Simplifying use of resource bundles using StringTemplate.Processor
// The template processor class below, LocalizationProcessor, simplifies working with resource bundles.
// For a given locale, it maps a string to a corresponding property in a resource bundle.
// Assuming there is a property-file resource bundle for each locale.
record LocalizationProcessor(Locale locale)
implements StringTemplate.Processor<String, RuntimeException> {
public String process(StringTemplate st) {
ResourceBundle resource = ResourceBundle.getBundle("resources", locale);
String stencil = String.join("_", st.fragments());
String msgFormat = resource.getString(stencil.replace(' ', '.'));
return MessageFormat.format(msgFormat, st.values().toArray());
}
}
class StringTemplatesSecondPreview {
public void print() {
System.out.println("# 7 # 459: String Templates (Second Preview)");
int x = 1;
int y = 2;
// Java 20
System.out.println("String.format - Java 20");
String stringFormat = String.format("%2$d plus %1$d equals %3$d", x, y, x + y);
System.out.println(stringFormat);
System.out.println("String.formatted - Java 20");
String stringFormatted = "%2$d plus %1$d equals %3$d".formatted(x, y, x + y);
System.out.println(stringFormatted);
System.out.println("MessageFormat format - Java 20");
MessageFormat formatMessage = new MessageFormat("{0} plus {1} equals {2}");
// https://openjdk.org/jeps/430 // Erratum
// MessageFormat mf = new MessageFormat("{0} plus {1} equals {2}");
// String s = mf.format(x, y, x + y); // error: no suitable method found for format(int,int,int)
String formatMessageFormat = formatMessage.format(stringFormat, x, y, x + y); //
System.out.println(formatMessageFormat);
System.out.println("The STR template processor");
System.out.print("""
STR is a template processor defined in the Java Platform.
It performs string interpolation by replacing each embedded expression in the template with the (stringified) value of that expression.
The result of evaluating a template expression which uses STR is a String; e.g., "This is Java"
""");
System.out.println("STR - Java 21");
String language = "Java";
String stringSTR = STR."Embedded expressions is \{language}";
System.out.println(stringSTR);
int number = 21;
stringSTR = STR."Embedded expressions is \{language} \{number}";
System.out.println(stringSTR);
System.out.println(STR."Embedded expressions can perform arithmetic: \{x} + \{y} = \{x + y}");
System.out.println(STR."Embedded expressions can invoke methods and access fields: \{x} to the power \{y} = \{Math.pow(x, y)}, Integer.MAX_VALUE = \{Integer.MAX_VALUE}");
System.out.println(System.getProperty("os.name"));
System.out.println(STR."\{System.getProperty("os.name").toLowerCase().contains("x") ? "Unix-like" : "Unique"} Operating System");
System.out.println(STR."LocalDate Now is \{LocalDate.now()}");
System.out.println(STR."LocalDateTime Now is \{LocalDateTime.now()}");
System.out.println(STR."ZonedDateTime Now is \{ZonedDateTime.now()}");
System.out.println(STR."LocalDate Now Format is \{DateTimeFormatter.ofPattern("EEEE, dd MMMM yyyy").format(LocalDate.now())}");
System.out.println(STR."LocalDateTime Now Format is \{DateTimeFormatter.ofPattern("h:mm:ss.SSS a").format(LocalDateTime.now())}");
String localDateTimePattern = "EEEE, dd MMMM yyyy, h:mm:ss.SSS a";
String zonedDateTimePattern = "EEEE, dd MMMM yyyy, z, h:mm:ss.SSS a";
System.out.println(STR."LocalDateTime Now Format is \{DateTimeFormatter.ofPattern(localDateTimePattern).format(LocalDateTime.now())}");
System.out.println(STR."ZonedDateTime Now Format is \{DateTimeFormatter.ofPattern(zonedDateTimePattern).format(ZonedDateTime.now())}");
int index = 0;
System.out.println(STR."Embedded expressions can be postfix increment expressions: index: \{index} index++: \{index++}, index--: \{index--}, ++index: \{++index}, --index: \{--index}");
String[] greek = { "Alpha", "Beta", "Gamma", "Delta", "Epsilon" };
System.out.println(STR."Embedded expression is a (nested) template expression: \{STR."\{greek[0]}, \{greek[1]}"}, \{greek[2]}, \{STR."\{greek[3]}, \{STR."\{greek[4]}"}"}");
String temp = STR."\{greek[3]}, \{greek[4]}";
temp = STR."\{greek[1]}, \{greek[2]}, \{temp}";
System.out.println(STR."\{greek[0]}, \{temp}");
System.out.println("Multi-line template expressions");
String title = "Home Page";
String text = "Hola!";
String html = STR."""
<html>
<head>
<title>\{title}</title>
</head>
<body>
<p>\{text}</p>
</body>
</html>
""";
System.out.print(html);
String project = "Open JDK";
String version = "21 Preview";
String license = "GPL-2.0-only with linking exception";
String json = STR."""
{
"project": "\{project}",
"version": "\{version}",
"license": "\{license}"
}
""";
System.out.print(json);
Rectangle[] zone = new Rectangle[] {
new Rectangle("Alpha", 17.8, 31.4),
new Rectangle("Beta", 9.6, 12.4),
new Rectangle("Gamma", 7.1, 11.23),
};
// https://openjdk.org/jeps/430 // Erratum
/*
String table = STR."""
Description Width Height Area
\{zone[0].name} \{zone[0].width} \{zone[0].height} \{zone[0].area()}
\{zone[1].name} \{zone[1].width} \{zone[1].height} \{zone[1].area()}
\{zone[2].name} \{zone[2].width} \{zone[2].height} \{zone[2].area()}
Total \{zone[0].area() + zone[1].area() + zone[2].area()}
""";
*/
String table = STR."""
Description \t Width \t Height Area
\{zone[0].name()} \t\t \{zone[0].width()} \t \{zone[0].height()} \t \{zone[0].area()}
\{zone[1].name()} \t\t \{zone[1].width()} \t \{zone[1].height()} \t \{zone[1].area()}
\{zone[2].name()} \t\t \{zone[2].width()} \t \{zone[2].height()} \t \{zone[2].area()}
Total \{zone[0].area() + zone[1].area() + zone[2].area()}
""";
System.out.print(table);
System.out.println("The FMT template processor");
System.out.print("""
FMT is another template processor defined in the Java Platform. FMT is like STR in that it performs interpolation, but it also interprets format specifiers which appear to the left of embedded expressions.
The format specifiers are the same as those defined in java.util.Formatter. Here is the zone table example, tidied up by format specifiers in the template.
""");
// table = FormatProcessor.FMT."""
table = FMT."""
Description Width Height Area
%-12s\{zone[0].name()} %7.2f\{zone[0].width()} %7.2f\{zone[0].height()} %7.2f\{zone[0].area()}
%-12s\{zone[1].name()} %7.2f\{zone[1].width()} %7.2f\{zone[1].height()} %7.2f\{zone[1].area()}
%-12s\{zone[2].name()} %7.2f\{zone[2].width()} %7.2f\{zone[2].height()} %7.2f\{zone[2].area()}
\{" ".repeat(0)}Total %7.2f\{zone[0].area() + zone[1].area() + zone[2].area()}
""";
System.out.print(table);
System.out.println("The RAW template processor");
System.out.println("RAW is a standard template processor that produces an unprocessed StringTemplate object.");
// StringTemplate stringTemplateRAW = StringTemplate.RAW."This is \{language}";
StringTemplate stringTemplateRAW = RAW."This is \{language}";
String processSTR = STR.process(stringTemplateRAW);
System.out.println(processSTR);
System.out.println("User-defined template processors");
stringTemplateRAW = RAW."\{x} plus \{x} equals \{x + y}";
String stringTemplateRAWToString = stringTemplateRAW.toString();
System.out.println(stringTemplateRAWToString);
stringTemplateRAW = RAW."\{x} plus \{y} equals \{x + y}";
List<String> fragments = stringTemplateRAW.fragments();
System.out.println(fragments);
String fragment = String.join("\\{}", fragments);
System.out.println(fragment);
List<Object> stringTemplateRAWValues = stringTemplateRAW.values();
System.out.println(stringTemplateRAWValues);
for (int i = 0, j = 1; i < 5; i++) {
stringTemplateRAW = RAW."\{i} plus \{j} yields \{i + j}";
System.out.println(stringTemplateRAW);
}
// var processorOf = StringTemplate.Processor.of((StringTemplate st) -> {
Processor<String, RuntimeException> processorOf = StringTemplate.Processor.of((StringTemplate st) -> {
String placeHolder = "•";
String stencil = String.join(placeHolder, st.fragments());
for (Object value : st.values()) {
String v = String.valueOf(value);
stencil = stencil.replaceFirst(placeHolder, v);
}
return stencil;
});
System.out.println(processorOf.getClass());
System.out.println(processorOf."\{x} plus \{y} equals \{x + y}");
processorOf = StringTemplate.Processor.of((StringTemplate st)-> {
StringBuilder sb = new StringBuilder();
Iterator<String> fragIter = st.fragments().iterator();
for (Object value : st.values()) {
sb.append(fragIter.next());
sb.append(value);
}
sb.append(fragIter.next());
return sb.toString();
});
System.out.println(processorOf."\{x} plus \{y} equals \{x + y}");
processorOf = StringTemplate.Processor.of(StringTemplate::interpolate);
System.out.println(processorOf."\{x} plus \{y} equals \{x + y}");
processorOf = StringTemplate.Processor.of(st -> st.interpolate().intern());
System.out.println(processorOf."\{x} plus \{y} equals \{x + y}");
System.out.println("Simplifying localization");
Locale thaiLocale = Locale.forLanguageTag("th-TH-u-nu-thai");
// https://openjdk.org/jeps/430 // Erratum
// FormatProcessor THAI = new FormatProcessor(thaiLocale);
FormatProcessor THAI = FormatProcessor.create(thaiLocale);
for (int i = 1; i <= 10000; i *= 10){
String s = THAI."This answer is %5d\{i}";
System.out.println(s);
}
}
}
class VectorAPISeventhIncubator {
// Simple scalar computation over elements of arrays
// Assume that the array arguments are of the same length
private void scalarComputation(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++) {
c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
}
System.out.println(Arrays.toString(c));
}
// Equivalent vector computation, using the Vector API
private static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;
private void vectorComputation(float[] a, float[] b, float[] c) {
int i = 0;
int upperBound = SPECIES.loopBound(a.length);
for (; i < upperBound; i += SPECIES.length()) {
// FloatVector va, vb, vc;
var va = FloatVector.fromArray(SPECIES, a, i);
var vb = FloatVector.fromArray(SPECIES, b, i);
var vc = va.mul(va)
.add(vb.mul(vb))
.neg();
vc.intoArray(c, i);
}
for (; i < a.length; i++) {
c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
}
System.out.println(Arrays.toString(c));
}
// On platforms supporting predicate registers, the above could be written more simply, without the scalar loop to process the tail elements, while still achieving optimal performance
private void vectorComputationPredicateRegisters(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
// VectorMask<Float> m;
var m = SPECIES.indexInRange(i, a.length);
// FloatVector va, vb, vc;
var va = FloatVector.fromArray(SPECIES, a, i, m);
var vb = FloatVector.fromArray(SPECIES, b, i, m);
var vc = va.mul(va)
.add(vb.mul(vb))
.neg();
vc.intoArray(c, i, m);
}
System.out.println(Arrays.toString(c));
}
public void print() {
System.out.println("# 8 # 460: Vector API (Seventh Incubator)");
float[] alpha = { 1.2f, 2.3f };
float[] beta = { 3.4f, 5.6f };
float[] gamma = { 7.8f, 9.1f };
System.out.println("Support the ARM Scalar Vector Extension (SVE) platform.");
System.out.println("Scalar Computation");
scalarComputation(alpha, beta, gamma);
System.out.println("Vector Computation");
vectorComputation(alpha, beta, gamma);
System.out.println("An API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPU architectures, thus achieving performance superior to equivalent scalar computations.");
vectorComputationPredicateRegisters(alpha, beta, gamma);
}
}
record BiggestInt(int limit) implements Gatherer<Integer, List<Integer>, Integer> {
// The Initializer Function creates a new private ArrayList to keep track of the largest integer across elements.
// The optional initializer function creates the gatherer's private state object.
// This creates an empty ArrayList with a capacity of only one Integer as its meant to store the largest Integer the gatherer has encountered so far.
@Override
public Supplier<List<Integer>> initializer() {
return () -> new ArrayList<Integer>(1);
}
// The Integrator Function
// Every gatherer requires an integrator function.
// To create an integrator function, call either Gatherer.Integrator.of(Gatherer.Integrator) or Gatherer.Integrator.ofGreedy(Gatherer.Integrator).
// These methods take as an argument a lambda expression that contains three parameters.
// This uses the following lambda expression:
@Override
public Integrator<List<Integer>, Integer, Integer> integrator() {
return Integrator.of(
(max, element, downstream) -> {
// Save the integer if it's the largest so far.
if (max.isEmpty()) {
max.addFirst(element);
}
else if (element > max.getFirst()) {
max.set(0, element);
}
// If the integer is equal or greater to the limit, "short-circuit": emit the current integer downstream, and return false to stop processing stream elements
if (element >= limit) {
downstream.push(element);
return false;
}
// Return true to continue processing stream elements
return true;
}
);
}
// The Combiner Function, which is used during parallel evaluation
// The optional combiner function is called only if you're running the gatherer in parallel.
// The combiner function is a lambda expression that contains two parameters, which represent two private state objects.
// This returns the private state object (an ArrayList) that contains the largest integer.
@Override
public BinaryOperator<List<Integer>> combiner() {
return (leftMax, rightMax) -> {
// If either the "left" or "right" ArrayLists contain no value, then return the other
if (leftMax.isEmpty()) {
return rightMax;
}
if (rightMax.isEmpty()) {
return leftMax;
}
// Return the ArrayList that contains the larger integer
int leftVal = leftMax.getFirst();
int rightVal = rightMax.getFirst();
if (leftVal > rightVal) {
return leftMax;
}
else {
return rightMax;
}
};
}
// The Finisher Function
// The optional finisher function is a lambda expression that contains two parameters:
// The parameter max is the private state object and downstream is a Gatherer.Downstream object.
// In this, the finisher function pushes the value contained in the private state object.
// Note that this value won't be pushed if the integrator function returned false.
// You can check whether a Downstream object is no longer processing input elements by calling the method Gatherer.Downstream::isRejecting.
// If it returns true, it's no longer processing input elements.
// Note: If the finisher function pushes a value downstream, then that value is contained in an Optional object.
@Override
public BiConsumer<List<Integer>, Downstream<? super Integer>> finisher() {
// Emit the largest integer, if there is one, downstream
return (max, downstream) -> {
if (!max.isEmpty()) {
downstream.push(max.getFirst());
}
};
}
}
class StreamGatherersPreview {
// Creating Gatherers with Factory Methods
// Instead of implementing the Gatherer interface, you can call one of the factory methods in the Gatherer interface to create a gatherer.
// The following is the same one as described in Creating a Gatherer except it calls the Gatherer::of method:
public Gatherer<Integer, List<Integer>, Integer> biggestInt(int limit) {
return Gatherer.of(
// Supplier
() -> { return new ArrayList<Integer>(1); },
// Integrator
Gatherer.Integrator.of(
(max, element, downstream) -> {
System.out.println("Processing " + element);
if (max.isEmpty()) max.addFirst(element);
else if (element > max.getFirst()) max.set(0, element);
if (element >= limit) {
downstream.push(element);
return false;
}
return true;
}
),
// Combiner
(leftMax, rightMax) -> {
if (leftMax.isEmpty()) return rightMax;
if (rightMax.isEmpty()) return leftMax;
int leftVal = leftMax.getFirst();
int rightVal = rightMax.getFirst();
if (leftVal > rightVal) return leftMax;
else return rightMax;
},
// Finisher
(max, downstream) -> {
if (!max.isEmpty()) {
downstream.push(max.getFirst());
}
}
);
}
public void print() {
System.out.println("# 9 # 461: Stream Gatherers (Preview)");
System.out.println("Record: new BiggestInt(555): " + new BiggestInt(555));
System.out.println("Gatherer (400, 300, 200, 777, 600, 800, 1000) gather(new BiggestInt(555) leftMax vs. rightMax findFirst");
System.out.println(Stream.of(400, 300, 200, 777, 600, 800, 1000)
.gather(new BiggestInt(555))
.findFirst()
.get());
System.out.println("Gatherer (400, 300, 200, 777, 600, 800, 1000) gather(new BiggestInt(555) parallel leftMax vs. rightMax findFirst");
System.out.println(Stream.of(400, 300, 200, 777, 600, 800, 1000)
.gather(new BiggestInt(555))
.parallel()
.findFirst()
.get());
System.out.println("Gatherers with Factory Methods (400, 300, 200, 777, 600, 800, 1000) gather(biggestInt(555)) leftMax vs. rightMax parallel");
System.out.println(Stream.of(400, 300, 200, 777, 600, 800, 1000)
.gather(biggestInt(555))
.parallel()
.findFirst()
.get());
System.out.println("Built-In Gatherers");
// Built-In Gatherers
// The Gatherers class contains the following built-in gatherers:
// fold(Supplier initial, BiFunction folder):
System.out.println("Gatherers.fold .forEach(): (2, 4, 6, 8): 6, (x, y) -> x * y)");
Stream.of(2, 4, 6, 8)
.gather(Gatherers.fold(() -> 6, (x, y) -> x * y))
.forEach(System.out::println);
// This is an many-to-one gatherer that constructs an aggregate incrementally until no more input elements exist.
// It has two parameters:
// initial: This is the identity value or the value that the gatherer emits if the input stream contains no elements.
// folder: This is a lambda expression that contains two parameters: the first is the aggregate the gatherer is constructing and the second is the element that's currently being processed.
// The following uses the fold gatherer to convert a stream of numbers to a semicolon-separated string:
System.out.println("Gatherers.fold .findFirst().get(): (2, 4, 6, 8): Comma Space Separated");
var commaSpaceSeparated = Stream.of(2, 4, 6, 8)
.gather(
Gatherers.fold(
() -> "",
(y, x) -> {
if (y.equals("")) {
return x.toString();
}
return y + ", " + x;
}
)
)
.findFirst()
.get();
System.out.println(commaSpaceSeparated);
// mapConcurrent(int maxConcurrency, Function mapper):
int maxConcurrency = 10;
System.out.println("Gatherers.mapConcurrent .forEach(): (2, 4, 6, 8): maxConcurrency, x -> x * 2");
Stream.of(2, 4, 6, 8)
.gather(Gatherers.mapConcurrent(maxConcurrency, x -> x * 2))
.forEach(System.out::println);
// This is a one-to-one gatherer that invokes mapper for each input element in the stream concurrently, up to the limit specified by maxConcurrency.
// You can use this limit for the following:
// As a rate-limiting construct to prevent the gatherer from issuing too many concurrent requests to things like an external service or a database
// As a performance-enhancer to enable multiple, separate operations to be performed concurrently while avoiding converting the entire stream into a parallel stream
// This gatherer preserves the ordering of the stream.
System.out.println("Gatherers.mapConcurrent .findFirst().get(): (2, 4, 6, 8): maxConcurrency, x -> x * 2");
var mapConcurrentFindFirstGet = Stream.of(2, 4, 6, 8)
.gather(Gatherers.mapConcurrent(maxConcurrency, x -> x * 2))
.findFirst()
.get();
System.out.println(mapConcurrentFindFirstGet);
// scan(Supplier initial, BiFunction scanner):
// This is a one-to-one gatherer that performs a prefix scan, which is an incremental accumulation.
// Starting with an initial value obtained from the parameter initial, it obtains subsequent values by applying scanner to the current value and the next input element.
// The gatherer then emits the value downstream.
System.out.println("Gatherers.scan .forEach(): (2, 4, 6, 8): 6, (x, y) -> x * y");
Stream.of(2, 4, 6, 8)
.gather(Gatherers.scan(() -> 6, (x, y) -> x * y))
.forEach(System.out::println);
// windowFixed(int windowSize):
// This is a many-to-many gatherer that gathers elements in windows, which are encounter-ordered groups of elements.
// The parameter windowSize specifies the size of the windows.
System.out.println("Gatherers.windowFixed: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10): windowFixed(3)");
List<List<Integer>> windows = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).gather(Gatherers.windowFixed(3)).toList();
windows.forEach(System.out::println);
// windowSliding(int windowSize):
// Similar to windowFixed, this is a many-to-many gatherer that gathers elements in windows.
// However, each subsequent window includes all elements of the previous window except for its first element, and adds the next element in the stream.
System.out.println("Gatherers.windowSliding: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10): windowSliding(3)");
List<List<Integer>> moreWindows = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).gather(Gatherers.windowSliding(3)).toList();
moreWindows.forEach(System.out::println);
// Composing Gatherers
// You can compose two or more gatherers into a single gatherer with the Gatherer.andThen(Gatherer).
System.out.println("Composing Gatherers with Gatherer.andThen(Gatherer): scan.andThen(fold): (1, 2, 3, 4, 5, 6, 7, 8, 9, 10): 100, (x, y) -> x + y)");
Gatherer<Integer, ?, Integer> scan = Gatherers.scan(() -> 100, (x, y) -> x + y);
Gatherer<Integer, ?, String> fold =
Gatherers.fold(() -> "",
(y, x) -> {
if (y.equals("")) {
return x.toString();
}
return y + "; " + x;
});
var t = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.gather(scan.andThen(fold))
.findFirst()
.get();
System.out.println(t);
}
}
// Java 20 Preview
class Task {
private final static ScopedValue<String> INNER_SCOPE = ScopedValue.newInstance();
public void execute() {
System.out.println("Before All Scopes OUTER_SCOPE: " + ScopedValuesSecondPreview.OUTER_SCOPE.get());
// Nested Scope
ScopedValue.where(INNER_SCOPE, "Inner Scople Run").run(() -> {
var outerScopeGet = ScopedValuesSecondPreview.OUTER_SCOPE.get();
var innerScopeGet = INNER_SCOPE.get();
System.out.println("Inner OUTER_SCOPE: " + outerScopeGet);
System.out.println("Inner INNER_SCOPE: " + innerScopeGet);
});
// Rebounded Scope
ScopedValue.where(ScopedValuesSecondPreview.OUTER_SCOPE, "Rebounded Outer Scope Run").run(() -> {
var reboundedOuterScopeGet = ScopedValuesSecondPreview.OUTER_SCOPE.get();
System.out.println("Rebounded OUTER_SCOPE: " + reboundedOuterScopeGet);
});
System.out.println("After All Scopes OUTER_SCOPE: " + ScopedValuesSecondPreview.OUTER_SCOPE.get());
}
}
// Common Shutdown Policies: ShutdownOnSuccess and ShutdownOnFailure
// The StructuredTaskScope class contains two subclasses, ShutdownOnFailure and ShutdownOnSuccess.
// These subclasses implement two common shutdown policies.
// ShutdownOnFailure cancels all subtasks if one of them fails, while ShutdownOnSuccess cancels all remaining subtasks if one of them succeeds.
// These shutdown policies are of short-circuiting patterns.
// A short-circuiting pattern encourages subtasks to complete quickly by enabling the main task to interrupt and cancel subtasks whose outcomes are no longer needed.
// The following is the StructuredTaskScope.ShutdownOnFailure and StructuredTaskScope.ShutdownOnSuccess classes.
// Each task scope forks five subtasks that sleep for a random duration of time. However, if the duration is greater than a specified threshold, the subtask throws a TooSlowException.
// The handleShutDownOnFailure() method prints the total duration of all subtasks if none of them threw an exception.
// The handleShutDownOnSuccess() method prints the duration of the subtask that is completed first.
class ShortCircuitingPattern {
class TooSlowException extends Exception {
public TooSlowException(String s) {
super(s);
}
}
public Integer randomTask(int maxDuration, int threshold) throws InterruptedException, TooSlowException {
int t = new Random().nextInt(maxDuration);
System.out.println("Duration: " + t);
if (t > threshold) {
throw new TooSlowException("Duration " + t + " greater than threshold " + threshold);
}
Thread.sleep(t);
return Integer.valueOf(t);
}
// StructuredTaskScope.ShutdownOnFailure class captures the first exception thrown by one of its subtasks, then invokes the shutdown method.
// This prevents any new subtasks from starting, interrupts all unfinished threads running other subtasks, and enables the application to continue running.
// To access the captured exception, call the ShutdownOnFailure::exception method.
// If you want to rethrow the exception instead, call the ShutdownOnFailure::throwIfFailed method, which this/
private void handleShutdownOnFailure() throws ExecutionException, InterruptedException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
List<Subtask<Integer>> subtasks = IntStream.range(0, 5)
.mapToObj(i -> scope.fork(() -> randomTask(1000, 850)))
.toList();
scope.join()
.throwIfFailed();
var totalDuration = subtasks.stream()
.map(t -> t.get())
.reduce(0, Integer::sum);
System.out.println("Total duration: " + totalDuration);
}
}
// StructuredTaskScope.ShutdownOnSuccess<T> class captures the result of the first subtask to be completed successfully, and like ShutdownOnFailure, invokes the shutdown method.
// To access the result of the subtask that completed successfully, call the ShutdownOnSuccess::result method, which this example demonstrates.
private void handleShutdownOnSuccess() throws ExecutionException, InterruptedException {
// try (var scope = new StructuredTaskScope.ShutdownOnSuccess<Integer>()) {
try (var scope = new StructuredTaskScope.ShutdownOnSuccess<>()) {
List<Subtask<Integer>> subtasks =
IntStream.range(0, 5)
.mapToObj(i -> scope.fork(() -> randomTask(1000, 850)))
.toList();
scope.join();
System.out.println("First task to finish: " + scope.result());
}
}
// Print the total duration of the subtasks that completed successfully and the exceptions of the subtasks that threw exceptions using ScopeZ<T>
// In the ScopeZ<T> class, before successfulTasks() and failedTasks() return streams for successSubtasks and failedSubtasks, respectively, it calls StructuredTaskScope::ensureOwnerAndJoined.
// This ensures that the example can only access successSubtasks and failedSubtasks provided that the current thread is the owner of the task scope, and the task scope has joined the subtasks after they have been forked.
private void handleSuccessfulAndFailedTasks() throws InterruptedException {
try (var scope = new ScopeZ<>()) {
var subtasks = IntStream.range(0, 5)
.mapToObj(i -> scope.fork(() -> randomTask(1000, 500)))
.toList();
scope.join();
var totalDuration = scope.successfulTasks()
.mapToInt(st -> (Integer)((Subtask)st).get())
.reduce(0, Integer::sum);
System.out.println("Total duration: " + totalDuration);
scope.failedTasks()
.forEach(ft ->
System.out.println(((Exception)((Subtask)ft).exception()).getMessage()));
}
}
public void randomTasks() {
try {
System.out.println("Running handle ShutdownOnFailure...");
handleShutdownOnFailure();
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
System.out.println("Running handle ShutdownOnSuccess<T>...");
handleShutdownOnSuccess();
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
System.out.println("Running handle Successful And Failed Tasks...");
handleSuccessfulAndFailedTasks();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
// Java 21 Preview
class ScopeX<T> extends StructuredTaskScope<T> {
private final Queue<T> results = new ConcurrentLinkedQueue<>();
ScopeX() { super(null, Thread.ofVirtual().factory()); }
// Java 21 Preview
@Override
protected void handleComplete(Subtask<? extends T> subtask) {
if (subtask.state() == Subtask.State.SUCCESS) {
results.add(subtask.get());
}
}
// Java 21 Preview
@Override
public ScopeX<T> join() throws InterruptedException {
super.join();
return this;
}
// Java 21 Preview
// Returns a stream of results from the subtasks that completed successfully
public Stream<T> results() {
super.ensureOwnerAndJoined();
return results.stream();
}
}
class ScopeY<T> extends StructuredTaskScope<T> {
private final Queue<Subtask<? extends T>> subtasks = new LinkedTransferQueue<>();
@Override
protected void handleComplete(Subtask<? extends T> subtask) {
if (subtask.state() == Subtask.State.SUCCESS) {
subtasks.add(subtask);
}
}
@Override
public ScopeY<T> join() throws InterruptedException {
super.join();
return this;
}
public Stream<Subtask<? extends T>> completedSuccessfully() {
super.ensureOwnerAndJoined();
return subtasks.stream();
}
}
public class ScopeZ<T> extends StructuredTaskScope<T> {
private final Queue<Subtask<? extends T>> successSubtasks = new LinkedTransferQueue<>();
private final Queue<Subtask<? extends T>> failedSubtasks = new LinkedTransferQueue<>();
@Override
protected void handleComplete(Subtask<? extends T> subtask) {
if (subtask.state() == Subtask.State.SUCCESS) {
successSubtasks.add(subtask);
} else if (subtask.state() == Subtask.State.FAILED) {
failedSubtasks.add(subtask);
}
}
@Override
public ScopeZ<T> join() throws InterruptedException {
super.join();
return this;
}
public Stream<Subtask<? extends T>> successfulTasks() {
super.ensureOwnerAndJoined();
return successSubtasks.stream();
}
public Stream<Subtask<? extends T>> failedTasks() {
super.ensureOwnerAndJoined();
return failedSubtasks.stream();
}
}
// Debugging StructuredTaskScope and Its Forked Subtasks with the jcmd Command
// The jcmd tool can emit a thread dump in JSON format.
// This thread dump displays the threads running the forked subtasks of a StructuredTaskScope in an array, along with their stack traces.
// The following that forks three subtasks.
// These subtasks repeatedly alternate between printing a message and sleeping for one second.
class ShortCircuitingPatternObservable {
private Long sleepOneSecond(String s) throws InterruptedException {
long pid = ProcessHandle.current().pid();
// for (int i = 0; i < 60; i++) {
for (int i = 0; i < 5; i++) {
System.out.println("[" + pid + ", " + s + "]" + " Sleeping for 1s...");
Thread.sleep(1000);
}
return Long.valueOf(pid);
}
private void handle() throws ExecutionException, InterruptedException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Supplier<Long> task1 = scope.fork(() -> sleepOneSecond("task1"));
Supplier<Long> task2 = scope.fork(() -> sleepOneSecond("task2"));
Supplier<Long> task3 = scope.fork(() -> sleepOneSecond("task3"));
scope.join()
.throwIfFailed();
}
}
public void print() {
try {
handle();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class StructuredConcurrencySecondPreview {
// Java 20 Preview
private <T> T getCallableTaskListResult(List<Callable<T>> callableTaskList) throws InterruptedException, ExecutionException {
try (var scope = new StructuredTaskScope.ShutdownOnSuccess<T>()) {
for (Callable<T> callableTask : callableTaskList) {
scope.fork(callableTask);
try {
System.out.println(callableTask.call());
} catch (Exception ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
}
scope.join();
return scope.result();
}
}
// Java 20 Preview
private void callableTaskListResult() {
Callable<String> callableAlpha = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Alpha"; };
Callable<String> callableBeta = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Beta"; };
Callable<String> callableGamma = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Gamma"; };
Callable<String> callableDelta = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Delta"; };
Callable<String> callableEpsilon = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Epsilon"; };
List<Callable<String>> callableTaskList = new ArrayList<>(Arrays.asList( callableAlpha, callableBeta, callableGamma, callableDelta, callableEpsilon));
try {
System.out.println("Callable Task List Result: " + getCallableTaskListResult(callableTaskList));
} catch (InterruptedException | ExecutionException ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
}
private String randomUUID() {
try {
Thread.sleep(Duration.ofSeconds(2L));
}
catch (InterruptedException ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
return UUID.randomUUID().toString();
}
private Integer randomNext() {
try {
Thread.sleep(Duration.ofSeconds(2L));
}
catch (InterruptedException ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
return new Random().nextInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
}
// Java 21 Preview
private String getRandom() {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// Java 21 Preview
Subtask<String> randomUUID = scope.fork(() -> this.randomUUID());
Subtask<Integer> randomNext = scope.fork(() -> this.randomNext());
try {
scope.join();
} catch (InterruptedException ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
return String.format("Random UUID = %s, Random Number = %d", randomUUID.get(), randomNext.get());
}
}
// Java 21 Preview
private List scopeXStructuredTaskScope() {
Callable<String> callableAlpha = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Alpha"; };
Callable<String> callableBeta = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Beta"; };
Callable<String> callableGamma = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Gamma"; };
Callable<String> callableDelta = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Delta"; };
Callable<String> callableEpsilon = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Epsilon"; };
List<Callable<String>> callableTaskList = new ArrayList<>(Arrays.asList( callableAlpha, callableBeta, callableGamma, callableDelta, callableEpsilon));
// Java 21 Preview
try (var scope = new ScopeX<String>()) {
// try (var scope = new StructuredTaskScope<String>()) {
List<Subtask<String>> subtasks = callableTaskList.stream().map(scope::fork).toList();
try {
scope.join();
} catch (InterruptedException ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
// System.out.println(scope.<String>results().toList());
return scope.results().toList();
} // close
}
// Java 21 Preview
private List collectingScopeStructuredTaskScope() {
Callable<String> callableAlpha = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Alpha"; };
Callable<String> callableBeta = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Beta"; };
Callable<String> callableGamma = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Gamma"; };
Callable<String> callableDelta = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Delta"; };
Callable<String> callableEpsilon = () -> { Thread.sleep(Duration.ofSeconds(1L)); return "Epsilon"; };
List<Callable<String>> callableTaskList = new ArrayList<>(Arrays.asList( callableAlpha, callableBeta, callableGamma, callableDelta, callableEpsilon));
// Java 21 Preview
try (var scope = new ScopeY<>()) {
// try (var scope = new StructuredTaskScope<>()) {
List<Subtask<String>> subtasks = callableTaskList.stream().map(scope::fork).toList();
try {
scope.join();
} catch (InterruptedException ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
// scope.<String>completedSuccessfully().forEach(x -> System.out.println( x.get()));
return scope.<String>completedSuccessfully().map(x -> x.get()).toList();
} // close
}
public void print() {
System.out.println("# 10 # 462: Structured Concurrency (Second Preview)");
System.out.println("StructuredTaskScope Callable...");
callableTaskListResult();
System.out.println("StructuredTaskScope Subtask...");
System.out.println(getRandom());
System.out.println("ScopeX<T> extends StructuredTaskScope<T>...");
System.out.println(scopeXStructuredTaskScope());
System.out.println("CollectingScope<T> extends StructuredTaskScope<T>...");
System.out.println(collectingScopeStructuredTaskScope());
System.out.println("Short Circuiting Pattern...");
var patternShortCircuiting = new ShortCircuitingPattern();
patternShortCircuiting.randomTasks();
System.out.println("Short Circuiting Pattern Observable...");
var observableShortCircuitingPattern = new ShortCircuitingPatternObservable();
observableShortCircuitingPattern.print();
}
}
class ScopedValuesSecondPreview {
private static final ScopedValue<Integer> RANDOM = ScopedValue.newInstance();
public static final ScopedValue<String> OUTER_SCOPE = ScopedValue.newInstance();
// Java 21 Preview
private void scopedValueWithStructuredTaskScope() {
// try (StructuredTaskScope<Object> scope = new StructuredTaskScope<>()) {
try (var scope = new StructuredTaskScope<>()) {
for (int i = 0; i< 10; i++) {
// Java 21 Preview
Subtask<Integer> task = scope.fork(() -> {
int randomNumber = ThreadLocalRandom.current().nextInt(1, 101);
ScopedValue.where(RANDOM, randomNumber).run(() -> {
System.out.println(String.format("ScopedValue With StructuredTaskScope: Thread %s: Random Number: %d", Thread.currentThread().threadId(), RANDOM.get()));
});
return null;
});
}
try {
scope.join();
} catch (InterruptedException ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
}
}
// Java 20 Preview
private void scopedValue() {
for (int i = 0; i < 10; i++) {
Thread scopedValueThread = new Thread(() -> {
int randomNumber = ThreadLocalRandom.current().nextInt(1, 101);
ScopedValue.where(RANDOM, randomNumber).run(() -> {
System.out.println(String.format("ScopedValue: Thread %s: Random Number: %d", Thread.currentThread().getName(), RANDOM.get()));
});
});
scopedValueThread.start();
try {
scopedValueThread.join();
} catch (InterruptedException ex) {
// ex.printStackTrace();
System.out.println(ex.getMessage());
}
}
}
// Java 20 Preview
private void scopedValueTask() {
ScopedValue.where(OUTER_SCOPE, "Outer Scope Run").run(() -> {
var tsk = new Task();
tsk.execute();
});
}
public void print() {
System.out.println("# 12 # 464: Scoped Values (Second Preview)");
System.out.println("ScopedValue...");
scopedValue();
System.out.println("ScopedValue With StructuredTaskScope...");
scopedValueWithStructuredTaskScope();
System.out.println("Scoped Value Task...");
scopedValueTask();
}
}
class SystemProperties {
public void print() {
System.out.println(String.format("OS Name: %s", System.getProperty("os.name")));
System.out.println(String.format("OS Version: %s", System.getProperty("os.version")));
System.out.println(String.format("OS Architecture: %s", System.getProperty("os.arch")));
System.out.println(String.format("Java Version: %s", System.getProperty("java.version")));
// System.getProperties().list(System.out);
}
}
/******************************************************************************/
/******************************************************************************/
// # 5 # 457: Class-File API (Preview)
/******************************************************************************/
// % java --enable-preview --source 22 --enable-native-access=ALL-UNNAMED --add-modules=jdk.incubator.vector Java22.java && java Program
// Or
// % java Program
/******************************************************************************/
/******************************************************************************/
// # 10 # 462: Structured Concurrency (Second Preview)
/******************************************************************************/
// While the class ShortCircuitingPatternObservable is running, create a thread dump by running the following command in a different console, where <pid> is the process ID of the running Java process.
// The thread dump output file shows the StructuredTaskScope with the threads of its forked subtasks in an array.
// The thread dump also shows the reference to the parent of the StructuredTaskScope so that the structure of the program can be reconstituted from the thread dump.
// Check the class ShortCircuitingPatternObservable for sleepOneSecond
// % Terminal New Window
// % jcmd <pid> Thread.dump_to_file -format=json output_file.txt
// use -overwrite to overwrite
// % jcmd <pid> Thread.dump_to_file -format=json output_file.txt -overwrite
/******************************************************************************/
/******************************************************************************/
// # 11 # 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
// % nano Program.java
/******************************************************************************/
/*
import java.util.Arrays;
void main(String[] args) {
var propertiesSystem = new SystemProperties();
propertiesSystem.print();
System.out.println();
System.out.println("String[] args: " + Arrays.toString(args));
System.out.println();
main();
}
// Java 21 Preview
void main() {
System.out.println("# 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)");
System.out.print("""
Allow the main method of a launched class to have public, protected, or default (i.e., package) access.
If the launched class contains a main method with a String[] parameter then choose that method.
Otherwise, if the class contains a main method with no parameters then choose that method.
In either case, if the chosen method is static then simply invoke it.
Otherwise, the chosen method is an instance method and the launched class must have a zero-parameter, non-private constructor (i.e., of public, protected, or package access). Invoke that constructor and then invoke the main method of the resulting object.
If there is no such constructor then report an error and terminate.
If there is no suitable main method then report an error and terminate
""");
}
// Can be at top-level
class SystemProperties {
public void print() {
System.out.println(String.format("OS Name: %s", System.getProperty("os.name")));
System.out.println(String.format("OS Version: %s", System.getProperty("os.version")));
System.out.println(String.format("OS Architecture: %s", System.getProperty("os.arch")));
System.out.println(String.format("Java Version: %s", System.getProperty("java.version")));
// System.getProperties().list(System.out);
}
}
*/
/******************************************************************************/
/******************************************************************************/
// NB
// # 11 # 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
// % nano Program.java
/******************************************************************************/
/*
import java.util.Arrays;
static void main(String[] args) {
// NB
// non-static variable this cannot be referenced from a static context viz. main(String[] args or static void main()
// var propertiesSystem = new SystemProperties();
// propertiesSystem.print();
var systemPropertiesStatic = new StaticSystemProperties();
systemPropertiesStatic.print();
System.out.println();
main();
}
static void main() {
// NB
// non-static variable this cannot be referenced from a static context viz. static void main() or static void main(String[] args)
// var propertiesSystem = new SystemProperties();
// propertiesSystem.print();
// var systemPropertiesStatic = new StaticSystemProperties();
// systemPropertiesStatic.print();
// System.out.println();
System.out.println("# 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)");
System.out.print("""
Allow the main method of a launched class to have public, protected, or default (i.e., package) access.
If the launched class contains a main method with a String[] parameter then choose that method.
Otherwise, if the class contains a main method with no parameters then choose that method.
In either case, if the chosen method is static then simply invoke it.
Otherwise, the chosen method is an instance method and the launched class must have a zero-parameter, non-private constructor (i.e., of public, protected, or package access). Invoke that constructor and then invoke the main method of the resulting object.
If there is no such constructor then report an error and terminate.
If there is no suitable main method then report an error and terminate
""");
}
// Can be at top-level
static class StaticSystemProperties {
public void print() {
System.out.println(String.format("OS Name: %s", System.getProperty("os.name")));
System.out.println(String.format("OS Version: %s", System.getProperty("os.version")));
System.out.println(String.format("OS Architecture: %s", System.getProperty("os.arch")));
System.out.println(String.format("Java Version: %s", System.getProperty("java.version")));
// System.getProperties().list(System.out);
}
}
*/
/******************************************************************************/
/******************************************************************************/
// NB
// # 6 # 458: Launch Multi-File Source-Code Programs
// % nano SourceCodeProgram.java
/******************************************************************************/
/*
class SourceCodeProgram {
static void printStatic() {
System.out.println("We enhance the java launcher's source-file mode to be able to run a program supplied as multiple files of Java source code.");
var programSourceCode2 = new SourceCodeProgram2();
programSourceCode2.printInstance2();
}
void printInstance() {
System.out.print("""
NB
When classes in different .java files refer to each other, the java launcher does not guarantee any particular order or timing for the compilation of the .java files.
It is possible, for example, for the launcher to compile the launched.java before the launcher. Some code may be compiled before the program starts executing while other code may be compiled lazily, on the fly.
""");
SourceCodeProgram2.printStatic2();
}
}
*/
/******************************************************************************/
/******************************************************************************/
// NB
// # 6 # 458: Launch Multi-File Source-Code Programs
// % nano SourceCodeProgram2.java
/******************************************************************************/
/*
import java.util.Locale;
class SourceCodeProgram2 {
static final Locale EN_US = Locale.of("en", "US");
static final String BOLD_TEXT = "\033[0;1m";
static final String RESET_TEXT = "\u001B[0m";
static void printStatic2() {
System.out.println(BOLD_TEXT + "static method 2 in SourceCodeProgram2".toUpperCase(EN_US) + RESET_TEXT);
}
void printInstance2() {
System.out.println(BOLD_TEXT + "Instance method 2 in SourceCodeProgram2".toUpperCase(EN_US) + RESET_TEXT);
}
}
*/
/******************************************************************************/
// Output
/*
WARNING: Using incubator modules: jdk.incubator.vector
OS Name: Mac OS X
OS Version: 14.4.1
OS Architecture: aarch64
Java Version: 22.0.2
# 1 # 423: Region Pinning for G1
Reduce latency by implementing region pinning in G1, so that garbage collection need not be disabled during Java Native Interface (JNI) critical regions.
Pinning regions during minor collection operations.
Maintain a count of the number of critical objects in each region:
Increment it when a critical object in that region is obtained, and decrement it when that object is released.
When the count is zero then garbage-collect the region normally; when the count is non-zero, consider the region to be pinned.
During a major collection, do not evacuate any pinned region.
During a minor collection, treat pinned regions in the young generation as having failed evacuation, thus promoting them to the old generation. Do not evacuate existing pinned regions in the old generation.
# 2 # 447: Statements before super(...) (Preview)
Java 22 Preview error: cannot reference super/this before supertype constructor has been called
Pre-Java 22 Preview error: call to super must be first statement in constructor
Pre-Java 22 Preview error: cannot reference this before supertype constructor has been called
# 3 # 454: Foreign Function & Memory API
radixsort input: [Delta, Gamma, Alpha, Beta]
radixsort output: [Alpha, Beta, Delta, Gamma]
strlen input: Hola!
strlen output: 5
qsort input: [5, 7, 9, 3, 4, 6, 1, 8, 2, 0]
qsort output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 4 # 456: Unnamed Variables & Patterns
Unnamed variables
The following kinds of declarations can introduce either a named variable (denoted by an identifier) or an unnamed variable (denoted by an underscore):
A local variable declaration statement in a block,
A resource specification of a try-with-resources statement,
The header of a basic for statement,
The header of an enhanced for loop,
An exception parameter of a catch block, and
A formal parameter of a lambda expression.
NumberFormatException: Java 21 Preview
Sum of 5 random numbers: 55
{=lowercase, epsilon=lowercase, alpha=lowercase, delta=lowercase, beta=lowercase, gamma=lowercase}
Unnamed pattern variables
An unnamed pattern variable can appear in a type pattern, including var type patterns, regardless of whether the type pattern appears at the top level or is nested in a record pattern.
By allowing us to elide names, unnamed pattern variables make run-time data exploration based on type patterns visually clearer, both in switch blocks and with the instanceof operator.
Multiple patterns in case labels
Currently, case labels are restricted to contain at most one pattern.
With the introduction of unnamed pattern variables and unnamed patterns, it is more likely that we will have within a single switch block several case clauses with different patterns but the same right-hand side.
Green Ball
A case label with multiple patterns can have a guard.
A guard governs the case as a whole, rather than the individual patterns.
RedBall, BlueBall, numeral = 777
Pairing a guard with each pattern is not allowed, so this is prohibited
The unnamed pattern
The unnamed pattern is an unconditional pattern that matches anything but declares and initializes nothing.
Like the unnamed type pattern var _ , the unnamed pattern can be nested in a record pattern.
It cannot, however, be used as a top-level pattern in, e.g., an instanceof expression or a case label.
The object is a PointUnnamed
The object is a PointUnnamed, x = 1
The object is a PointUnnamed, x = 1
The object is ColoredPointUnnameds, x = 1, y = 2
The object is ColoredPointUnnamed, c = BLUE
The object is ColoredPointUnnameds, x = 1
The object is ColoredPointUnnamed x = 1, c = BLUE
# 5 # 457: Class-File API (Preview)
Program.class created successfully, run java Program in the console to get the output of Java Version
# 6 # 458: Launch Multi-File Source-Code Programs
We enhance the java launcher's source-file mode to be able to run a program supplied as multiple files of Java source code.
INSTANCE METHOD 2 IN SOURCECODEPROGRAM2
NB
When classes in different .java files refer to each other, the java launcher does not guarantee any particular order or timing for the compilation of the .java files.
It is possible, for example, for the launcher to compile the launched.java before the launcher. Some code may be compiled before the program starts executing while other code may be compiled lazily, on the fly.
STATIC METHOD 2 IN SOURCECODEPROGRAM2
# 7 # 459: String Templates (Second Preview)
String.format - Java 20
2 plus 1 equals 3
String.formatted - Java 20
2 plus 1 equals 3
MessageFormat format - Java 20
2 plus 1 equals 3
The STR template processor
STR is a template processor defined in the Java Platform.
It performs string interpolation by replacing each embedded expression in the template with the (stringified) value of that expression.
The result of evaluating a template expression which uses STR is a String; e.g., "This is Java"
STR - Java 21
Embedded expressions is Java
Embedded expressions is Java 21
Embedded expressions can perform arithmetic: 1 + 2 = 3
Embedded expressions can invoke methods and access fields: 1 to the power 2 = 1.0, Integer.MAX_VALUE = 2147483647
Mac OS X
Unix-like Operating System
LocalDate Now is 2024-09-01
LocalDateTime Now is 2024-09-01T09:02:12.722955
ZonedDateTime Now is 2024-09-01T09:02:12.723315+05:30[Asia/Kolkata]
LocalDate Now Format is Sunday, 01 September 2024
LocalDateTime Now Format is 9:02:12.729 AM
LocalDateTime Now Format is Sunday, 01 September 2024, 9:02:12.729 AM
ZonedDateTime Now Format is Sunday, 01 September 2024, IST, 9:02:12.729 AM
Embedded expressions can be postfix increment expressions: index: 0 index++: 0, index--: 1, ++index: 1, --index: 0
Embedded expression is a (nested) template expression: Alpha, Beta, Gamma, Delta, Epsilon
Alpha, Beta, Gamma, Delta, Epsilon
Multi-line template expressions
<html>
<head>
<title>Home Page</title>
</head>
<body>
<p>Hola!</p>
</body>
</html>
{
"project": "Open JDK",
"version": "21 Preview",
"license": "GPL-2.0-only with linking exception"
}
Description Width Height Area
Alpha 17.8 31.4 558.92
Beta 9.6 12.4 119.03999999999999
Gamma 7.1 11.23 79.733
Total 757.693
The FMT template processor
FMT is another template processor defined in the Java Platform. FMT is like STR in that it performs interpolation, but it also interprets format specifiers which appear to the left of embedded expressions.
The format specifiers are the same as those defined in java.util.Formatter. Here is the zone table example, tidied up by format specifiers in the template.
Description Width Height Area
Alpha 17.80 31.40 558.92
Beta 9.60 12.40 119.04
Gamma 7.10 11.23 79.73
Total 757.69
The RAW template processor
RAW is a standard template processor that produces an unprocessed StringTemplate object.
This is Java
User-defined template processors
StringTemplate{ fragments = [ "", " plus ", " equals ", "" ], values = [1, 1, 3] }
[, plus , equals , ]
\{} plus \{} equals \{}
[1, 2, 3]
StringTemplate{ fragments = [ "", " plus ", " yields ", "" ], values = [0, 1, 1] }
StringTemplate{ fragments = [ "", " plus ", " yields ", "" ], values = [1, 1, 2] }
StringTemplate{ fragments = [ "", " plus ", " yields ", "" ], values = [2, 1, 3] }
StringTemplate{ fragments = [ "", " plus ", " yields ", "" ], values = [3, 1, 4] }
StringTemplate{ fragments = [ "", " plus ", " yields ", "" ], values = [4, 1, 5] }
class java.lang.StringTemplate$Processor$$Lambda/0x000000040124ccc0
1 plus 2 equals 3
1 plus 2 equals 3
1 plus 2 equals 3
1 plus 2 equals 3
Simplifying localization
This answer is ๑
This answer is ๑๐
This answer is ๑๐๐
This answer is ๑๐๐๐
This answer is ๑๐๐๐๐
# 8 # 460: Vector API (Seventh Incubator)
Support the ARM Scalar Vector Extension (SVE) platform.
Scalar Computation
[-13.0, -36.649998]
Vector Computation
[-13.0, -36.649998]
An API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPU architectures, thus achieving performance superior to equivalent scalar computations.
[-13.0, -36.649998]
# 9 # 461: Stream Gatherers (Preview)
Record: new BiggestInt(555): BiggestInt[limit=555]
Gatherer (400, 300, 200, 777, 600, 800, 1000) gather(new BiggestInt(555) leftMax vs. rightMax findFirst
777
Gatherer (400, 300, 200, 777, 600, 800, 1000) gather(new BiggestInt(555) parallel leftMax vs. rightMax findFirst
777
Gatherers with Factory Methods (400, 300, 200, 777, 600, 800, 1000) gather(biggestInt(555)) leftMax vs. rightMax parallel
Processing 600
Processing 300
Processing 400
Processing 777
Processing 200
777
Built-In Gatherers
Gatherers.fold .forEach(): (2, 4, 6, 8): 6, (x, y) -> x * y)
2304
Gatherers.fold .findFirst().get(): (2, 4, 6, 8): Comma Space Separated
2, 4, 6, 8
Gatherers.mapConcurrent .forEach(): (2, 4, 6, 8): maxConcurrency, x -> x * 2
4
8
12
16
Gatherers.mapConcurrent .findFirst().get(): (2, 4, 6, 8): maxConcurrency, x -> x * 2
4
Gatherers.scan .forEach(): (2, 4, 6, 8): 6, (x, y) -> x * y
12
48
288
2304
Gatherers.windowFixed: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10): windowFixed(3)
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
[10]
Gatherers.windowSliding: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10): windowSliding(3)
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]
[8, 9, 10]
Composing Gatherers with Gatherer.andThen(Gatherer): scan.andThen(fold): (1, 2, 3, 4, 5, 6, 7, 8, 9, 10): 100, (x, y) -> x + y)
101; 103; 106; 110; 115; 121; 128; 136; 145; 155
# 10 # 462: Structured Concurrency (Second Preview)
StructuredTaskScope Callable...
Alpha
Beta
Gamma
Delta
Epsilon
Callable Task List Result: Alpha
StructuredTaskScope Subtask...
Random UUID = b612f660-d477-4d61-aeda-f7f148519851, Random Number = -897354483
ScopeX<T> extends StructuredTaskScope<T>...
[Beta, Delta, Gamma, Alpha, Epsilon]
CollectingScope<T> extends StructuredTaskScope<T>...
[Delta, Beta, Gamma, Epsilon, Alpha]
Short Circuiting Pattern...
Running handle ShutdownOnFailure...
Duration: 987
Duration: 672
Duration: 991
Duration: 737
Duration: 728
Java22$ShortCircuitingPattern$TooSlowException: Duration 987 greater than threshold 850
Running handle ShutdownOnSuccess<T>...
Duration: 845
Duration: 222
Duration: 445
Duration: 408
Duration: 607
First task to finish: 222
Running handle Successful And Failed Tasks...
Duration: 28
Duration: 570
Duration: 948
Duration: 65
Duration: 489
Total duration: 582
Duration 570 greater than threshold 500
Duration 948 greater than threshold 500
Short Circuiting Pattern Observable...
[26897, task3] Sleeping for 1s...
[26897, task1] Sleeping for 1s...
[26897, task2] Sleeping for 1s...
[26897, task1] Sleeping for 1s...
[26897, task3] Sleeping for 1s...
[26897, task2] Sleeping for 1s...
[26897, task1] Sleeping for 1s...
[26897, task3] Sleeping for 1s...
[26897, task2] Sleeping for 1s...
[26897, task3] Sleeping for 1s...
[26897, task1] Sleeping for 1s...
[26897, task2] Sleeping for 1s...
[26897, task1] Sleeping for 1s...
[26897, task3] Sleeping for 1s...
[26897, task2] Sleeping for 1s...
# 11 # 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)
Allow the main method of a launched class to have public, protected, or default (i.e., package) access.
If the launched class contains a main method with a String[] parameter then choose that method.
Otherwise, if the class contains a main method with no parameters then choose that method.
In either case, if the chosen method is static then simply invoke it.
Otherwise, the chosen method is an instance method and the launched class must have a zero-parameter, non-private constructor (i.e., of public, protected, or package access). Invoke that constructor and then invoke the main method of the resulting object.
If there is no such constructor then report an error and terminate.
If there is no suitable main method then report an error and terminate
# 12 # 464: Scoped Values (Second Preview)
ScopedValue...
ScopedValue: Thread Thread-0: Random Number: 74
ScopedValue: Thread Thread-1: Random Number: 47
ScopedValue: Thread Thread-2: Random Number: 91
ScopedValue: Thread Thread-3: Random Number: 11
ScopedValue: Thread Thread-4: Random Number: 48
ScopedValue: Thread Thread-5: Random Number: 80
ScopedValue: Thread Thread-6: Random Number: 17
ScopedValue: Thread Thread-7: Random Number: 82
ScopedValue: Thread Thread-8: Random Number: 88
ScopedValue: Thread Thread-9: Random Number: 43
ScopedValue With StructuredTaskScope...
ScopedValue With StructuredTaskScope: Thread 88: Random Number: 13
ScopedValue With StructuredTaskScope: Thread 97: Random Number: 32
ScopedValue With StructuredTaskScope: Thread 90: Random Number: 100
ScopedValue With StructuredTaskScope: Thread 89: Random Number: 33
ScopedValue With StructuredTaskScope: Thread 91: Random Number: 20
ScopedValue With StructuredTaskScope: Thread 93: Random Number: 90
ScopedValue With StructuredTaskScope: Thread 94: Random Number: 9
ScopedValue With StructuredTaskScope: Thread 95: Random Number: 52
ScopedValue With StructuredTaskScope: Thread 92: Random Number: 41
ScopedValue With StructuredTaskScope: Thread 96: Random Number: 84
Scoped Value Task...
Before All Scopes OUTER_SCOPE: Outer Scope Run
Inner OUTER_SCOPE: Outer Scope Run
Inner INNER_SCOPE: Inner Scople Run
Rebounded OUTER_SCOPE: Rebounded Outer Scope Run
After All Scopes OUTER_SCOPE: Outer Scope Run
Java Version: 22.0.2
*/
// Credits
/*
https://openjdk.org/
https://java.com/
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment