Fundamentals 15 min read

Explore Java 23’s 12 New Features and Upcoming JEP Previews

Java 23 arrives as a non‑LTS release introducing 12 new language features, while a series of JEP previews—including pattern‑matching for primitives, class‑file API, Markdown Javadoc, Vector API, scoped values, flexible constructors, and structured concurrency—are detailed with code examples and insights for developers.

macrozheng
macrozheng
macrozheng
Explore Java 23’s 12 New Features and Upcoming JEP Previews

Java 23 is a non‑LTS release, supported for six months; the next LTS version will be Java 25.

Java 23 adds 12 new language features, which are explained below.

JEP 455: Pattern Matching for Primitive Types, instanceof and switch (preview)

Before JEP 455,

instanceof

only supported reference types and

switch

/

case

labels could use only integer literals, enum constants, or string literals. The preview expands

instanceof

and

switch

to support all primitive types:

byte

,

short

,

char

,

int

,

long

,

float

,

double

, and

boolean

.

<code>// traditional way
if (i >= -128 && i <= 127) {
    byte b = (byte)i;
    ... b ...
}

// using instanceof
if (i instanceof byte b) {
    ... b ...
}

long v = ...;
// traditional switch
if (v == 1L) {
    // ...
} else if (v == 2L) {
    // ...
} else if (v == 10_000_000_000L) {
    // ...
}

// using long case labels
switch (v) {
    case 1L:
        // ...
        break;
    case 2L:
        // ...
        break;
    case 10_000_000_000L:
        // ...
        break;
    default:
        // ...
}</code>

JEP 456: Class‑File API (second preview)

The Class‑File API, first previewed in Java 22, provides a standardized way to parse, generate, and transform Java class files, reducing reliance on third‑party libraries such as ASM.

<code>// Create a ClassFile object – the entry point for class‑file manipulation.
ClassFile cf = ClassFile.of();
// Parse a byte array into a ClassModel.
ClassModel classModel = cf.parse(bytes);

// Build a new class file, removing all methods whose names start with "debug".
byte[] newBytes = cf.build(classModel.thisClass().asSymbol(),
    classBuilder -> {
        // Iterate over all class elements.
        for (ClassElement ce : classModel) {
            // Keep elements that are not methods starting with "debug".
            if (!(ce instanceof MethodModel mm && mm.methodName().stringValue().startsWith("debug"))) {
                classBuilder.with(ce);
            }
        }
    });</code>

JEP 467: Markdown Documentation Comments

JavaDoc now supports Markdown syntax, allowing developers to write documentation more concisely while still supporting HTML elements and JavaDoc tags.

JEP 469: Vector API (eighth incubation)

The Vector API enables expressive, platform‑independent vector computations that the JVM can compile to optimal SIMD instructions, offering performance superior to equivalent scalar code.

<code>// scalar computation
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;
    }
}
</code>
<code>static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;

void vectorComputation(float[] a, float[] b, float[] c) {
    int i = 0;
    int upperBound = SPECIES.loopBound(a.length);
    for (; i < upperBound; i += SPECIES.length()) {
        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;
    }
}
</code>

JEP 473: Stream Collectors (second preview)

This improvement allows the Stream API to support custom intermediate operations.

<code>source.gather(a).gather(b).gather(c).collect(...)</code>

JEP 471: Deprecate Unsafe Memory Access Methods

Methods in

sun.misc.Unsafe

for memory access are deprecated in favor of safer alternatives such as

java.lang.invoke.VarHandle

and

java.lang.foreign.MemorySegment

, which are core components of the Foreign Function & Memory API introduced in Java 22.

JEP 476: Module Import Declarations (preview)

Module import declarations let developers import all exported packages of a module with a single statement, simplifying code that uses many modules.

<code>// Import the entire java.base module
import module java.base;

public class Example {
    public static void main(String[] args) {
        String[] fruits = { "apple", "berry", "citrus" };
        Map<String, String> fruitMap = Stream.of(fruits)
            .collect(Collectors.toMap(
                s -> s.toUpperCase().substring(0, 1),
                Function.identity()));
        System.out.println(fruitMap);
    }
}
</code>

JEP 477: Unnamed Classes and Instance main Methods (third preview)

This feature simplifies the declaration of

main

methods, allowing code without an explicit class name.

<code>// Traditional main method
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

// Using unnamed class
class HelloWorld {
    void main() {
        System.out.println("Hello, World!");
    }
}

// Fully unnamed class
void main() {
    System.out.println("Hello, World!");
}
</code>

JEP 480: Structured Concurrency (third preview)

Structured concurrency treats multiple tasks running in different threads as a single unit of work, simplifying error handling and improving observability. The core API is

StructuredTaskScope

.

<code>try (var scope = new StructuredTaskScope<Object>()) {
    Future<Integer> future1 = scope.fork(task1);
    Future<String>  future2 = scope.fork(task2);
    scope.join();
    // process results or rethrow exceptions
} // close
</code>

JEP 481: Scoped Values (third preview)

Scoped values provide immutable data that can be shared across threads, offering a safer alternative to thread‑local variables, especially with many virtual threads.

<code>final static ScopedValue<...> V = new ScopedValue<>();

// In some method
ScopedValue.where(V, <value>)
    .run(() -> { ... V.get() ... call methods ... });

// In a method called directly or indirectly from the lambda
... V.get() ...
</code>

JEP 482: Flexible Constructor Bodies (second preview)

This preview allows statements to appear before the

super(...)

or

this(...)

call in a constructor, enabling field initialization and validation without relying on helper methods.

<code>class Person {
    private final String name;
    private int age;

    public Person(String name, int age) {
        if (age < 0) {
            throw new IllegalArgumentException("Age cannot be negative.");
        }
        this.name = name; // initialize before super
        this.age = age;
        // ... other initialization code
    }
}

class Employee extends Person {
    private final int employeeId;

    public Employee(String name, int age, int employeeId) {
        this.employeeId = employeeId; // initialize before super
        super(name, age);
        // ... other initialization code
    }
}
</code>
JavaConcurrencylanguage featurespreviewJEPJava23
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.