Java 22 新特性解析与代码示例

发布于:2025-08-02 ⋅ 阅读:(15) ⋅ 点赞:(0)

Java 22 新特性解析与代码示例

1. 引言

Java 22(2024年3月19日发布)是Java平台的又一重要版本,带来了12个JDK增强提案(JEPs),涵盖了语言特性、虚拟机优化、并发编程和本地代码交互等多个方面。这些特性不仅提升了Java的性能和安全性,还为开发者提供了更灵活、更高效的编程方式。本文将深入剖析Java 22的所有新特性,包括标准特性和预览特性,并通过完整的代码示例和对比说明,帮助读者全面理解和掌握这些特性。

本文将涵盖以下JEPs:

JEP ID Feature (特性)
特性名称
Status (状态)
状态
Description (描述)
描述
JEP 423 Region Pinning for G1
G1 区域固定
Final (正式) 在 JNI 的关键区域期间继续进行垃圾回收,减少暂停时间,提高性能。
JEP 447 Statements before super(…)
super() 之前的语句
Preview (预览) 构造函数中允许在 super() 调用之前编写不引用 this 的语句。
JEP 454 Foreign Function & Memory API
外部函数与内存 API
Final (正式) 安全高效地调用本地函数和访问本地内存,取代 JNI。
JEP 456 Unnamed Variables & Patterns
未命名变量与模式
Final (正式) 使用 _ 表示未使用的变量或模式,减少冗余,提高可读性。
JEP 457 Class-File API
类文件 API
Preview (预览) 提供标准化 API 解析和生成 Java 类文件,取代 ASM 等第三方库。
JEP 458 Launch Multi-File Source-Code Programs
多文件源程序启动
Final (正式) Java 命令可直接运行多个源文件,无需预先编译。
JEP 459 String Templates (Second Preview)
字符串模板(二次预览)
Preview (预览) 使用 STR 模板内嵌表达式构建字符串,简化代码。Java 23 中已撤回。
JEP 460 Vector API (Seventh Incubator)
向量 API(第七次孵化)
Incubator (孵化) 利用 SIMD 指令提升性能,适用于密集计算场景。
JEP 461 Stream Gatherers
流收集器
Preview (预览) 为 Stream API 添加自定义中间操作,提高灵活性。
JEP 462 Structured Concurrency (Second Preview)
结构化并发(二次预览)
Preview (预览) 结构化管理并发任务,提升可靠性与可观察性。
JEP 463 Implicitly Declared Classes and Instance Main Methods
隐式类与实例主方法(二次预览)
Preview (预览) 支持无类声明和实例主方法,简化入门和小程序编写。
JEP 464 Scoped Values (Second Preview)
作用域值(二次预览)
Preview (预览) 在线程间安全共享不可变数据,替代 ThreadLocal。

每个特性都将得到详细的解释和示例说明,帮助读者在实际开发中应用这些新功能。以下内容将按照JEP编号顺序逐一展开。

在这里插入图片描述

2. G1 区域固定:JEP 423: Region Pinning for G1

概述

JEP 423 引入了G1垃圾收集器的区域固定(Region Pinning)特性,允许在Java Native Interface (JNI) 的关键区域(critical regions)期间继续进行垃圾收集,从而减少延迟并提高性能。这一特性主要优化了使用JNI的应用程序的垃圾收集行为。

背景

在Java中,JNI允许Java代码与本地代码(如C/C++)交互。然而,在使用JNI的关键区域(如通过GetPrimitiveArrayCritical获取的内存区域)时,垃圾收集器通常需要暂停,以防止本地代码访问的内存被移动或回收。这会导致显著的延迟,尤其是在高吞吐量或低延迟要求的场景中。

解决方案

JEP 423通过区域固定技术解决了这一问题。垃圾收集器现在可以固定包含关键对象的内存区域,允许在不中断本地代码执行的情况下继续收集其他区域。这显著减少了垃圾收集暂停时间,提高了性能。

示例

由于区域固定是垃圾收集器的内部优化,开发者无需修改代码即可受益。以下是一个使用JNI的示例,展示如何调用本地方法:

public class NativeExample {
    public static void main(String[] args) {
        nativeMethod();
    }

    private static native void nativeMethod();
}

对应的C代码如下:

JNIEXPORT void JNICALL Java_NativeExample_nativeMethod(JNIEnv *env, jobject obj) {
    jintArray array = (*env)->NewIntArray(env, 10);
    jint *elements = (*env)->GetPrimitiveArrayCritical(env, array, NULL);
    if (elements == NULL) {
        // 处理错误
        return;
    }
    // 使用 elements
    (*env)->ReleasePrimitiveArrayCritical(env, array, elements, 0);
}

在JEP 423之前,垃圾收集器在GetPrimitiveArrayCriticalReleasePrimitiveArrayCritical之间会暂停。现在,垃圾收集器可以固定包含elements的区域,继续收集其他区域。

好处

  • 降低延迟:减少了JNI关键区域导致的垃圾收集暂停时间。
  • 提高性能:对使用JNI的应用程序(如数据库驱动或图形库)性能提升显著。
  • 无缝集成:开发者无需修改现有代码即可享受性能提升。

注意事项

  • 这一特性是标准特性,适用于所有使用G1垃圾收集器的Java 22应用程序。
  • 开发者应注意,区域固定可能增加内存使用量,因为固定区域在垃圾收集期间无法回收。

参考

3. super() 之前的语句:JEP 447: Statements before super(…) (Preview)

概述

JEP 447允许在构造函数中调用super()this()之前添加不引用当前实例(this)的语句。这一预览特性为开发者提供了更大的灵活性,可以在调用超类构造函数之前执行验证或其他逻辑。

背景

在Java中,构造函数的第一条语句必须是super()this(),这限制了在构造函数中添加初始化逻辑的能力。开发者通常需要通过静态方法或其他构造函数来实现这些逻辑,增加了代码复杂性。

解决方案

JEP 447放宽了这一限制,允许在super()之前添加不引用this的语句。这使得构造函数的逻辑表达更加自然。

示例

以下是一个示例,展示如何在构造函数中验证参数:

import java.math.BigInteger;

public class PositiveBigInteger extends BigInteger {
    public PositiveBigInteger(long value) {
        if (value <= 0) {
            throw new IllegalArgumentException("non-positive value");
        }
        super(String.valueOf(value));
    }

    public static void main(String[] args) {
        try {
            PositiveBigInteger num = new PositiveBigInteger(-1);
        } catch (IllegalArgumentException e) {
            System.out.println(e.getMessage()); // 输出: non-positive value
        }
    }
}

对比
在Java 22之前,开发者需要将验证逻辑放入静态方法或辅助构造函数中:

import java.math.BigInteger;

public class PositiveBigIntegerOld extends BigInteger {
    public PositiveBigIntegerOld(long value) {
        super(validate(value));
    }

    private static String validate(long value) {
        if (value <= 0) {
            throw new IllegalArgumentException("non-positive value");
        }
        return String.valueOf(value);
    }
}

新版本的代码更简洁,直接在构造函数中完成验证。

好处

  • 简化代码:减少了对辅助方法或构造函数的依赖。
  • 提高可读性:逻辑直接在构造函数中表达,更直观。
  • 灵活性:支持更复杂的初始化逻辑。

注意事项

  • 语句不得引用this,否则会导致编译错误。
  • 需使用--enable-preview标志启用此预览特性。
  • 作为预览特性,未来版本可能会有调整。

参考

4. 外部函数与内存 API:JEP 454: Foreign Function & Memory API

概述

JEP 454引入了Foreign Function & Memory API(FFM API),这是一个标准化的API,用于Java程序与本地代码和内存交互,旨在取代传统的Java Native Interface (JNI)。FFM API提供了更安全、更高效的交互方式。

背景

JNI虽然功能强大,但其复杂性和易出错性使其难以使用。此外,JNI的性能开销较高,尤其是在频繁调用本地代码时。FFM API的目标是提供一个更简单、更安全的替代方案。

解决方案

FFM API允许Java程序直接调用本地函数(如C/C++函数)并安全访问非JVM管理的内存。它通过java.lang.foreign包提供支持,简化了本地代码交互。

示例

以下是一个示例,展示如何使用FFM API调用C语言的printf函数:

import java.lang.foreign.*;
import java.nio.charset.Charset;

public class FFMExample {
    public static void main(String[] args) throws Throwable {
        SymbolLookup lookup = SymbolLookup.loaderLookup();
        MemorySegment printf = lookup.find("printf").orElseThrow();
        MemorySegment format = Arena.ofAuto().allocateUtf8String("Hello, %s!%n");
        MemorySegment name = Arena.ofAuto().allocateUtf8String("World");

        FunctionDescriptor desc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS);
        MethodHandle handle = Linker.nativeLinker().downcallHandle(printf, desc);

        handle.invoke(format, name);
    }
}

对比
使用JNI调用相同的printf函数需要更多的样板代码:

public class JNIExample {
    static {
        System.loadLibrary("example");
    }

    public static void main(String[] args) {
        callPrintf("World");
    }

    private static native void callPrintf(String name);
}

对应的C代码:

#include <jni.h>
#include <stdio.h>

JNIEXPORT void JNICALL Java_JNIExample_callPrintf(JNIEnv *env, jclass cls, jstring name) {
    const char *cName = (*env)->GetStringUTFChars(env, name, NULL);
    printf("Hello, %s!\n", cName);
    (*env)->ReleaseStringUTFChars(env, name, cName);
}

FFM API的代码更简洁,且无需编写JNI头文件和复杂的C代码。

好处

  • 简洁性:减少了样板代码,提高了开发效率。
  • 安全性:提供内存管理的抽象,降低内存泄漏风险。
  • 性能:优化的本地调用机制提高了性能。

注意事项

  • 需要确保本地库可用并正确配置。
  • FFM API是标准特性,但仍需熟悉其API设计。

参考

5. 未命名变量与模式:JEP 456: Unnamed Variables & Patterns

概述

JEP 456引入了未命名变量和模式(Unnamed Variables & Patterns),允许使用_表示不需要使用的变量或模式,从而减少代码冗余,提高可读性。这一特性在Java 22中成为标准特性。

背景

在Java中,某些场景要求声明变量或模式,但这些变量可能在后续代码中未被使用,导致代码显得冗长。例如,在循环或模式匹配中,开发者可能只关心某些部分的数据。

解决方案

JEP 456允许使用_作为占位符,表示未使用的变量或模式,适用于循环、异常处理、lambda表达式和模式匹配等场景。

示例

以下是一个示例,展示未命名变量和模式的使用:

import java.util.Arrays;

public class UnnamedExample {
    public static void main(String[] args) {
        // 未命名变量在循环中
        int total = 0;
        for (Integer _ : Arrays.asList(1, 2, 3)) {
            total++;
        }
        System.out.println("Total: " + total);

        // 未命名模式在switch中
        record Person(String name, int age) {}
        Person person = new Person("Alice", 30);
        switch (person) {
            case Person(String _, int _) -> System.out.println("Person found");
        }
    }
}

对比
在Java 22之前,开发者需要为未使用的变量命名:

int total = 0;
for (Integer number : Arrays.asList(1, 2, 3)) {
    total++;
}

新版本的代码更简洁,意图更清晰。

好处

  • 减少冗余:避免为未使用变量命名。
  • 提高可读性:代码更简洁,意图更明确。
  • 广泛适用:支持多种场景,如循环、异常处理和模式匹配。

注意事项

  • _仅用于未使用的变量或模式,不能用于需要引用的变量。
  • 作为标准特性,可直接在Java 22中使用。

参考

6. 类文件 API:JEP 457: Class-File API (Preview)

概述

JEP 457引入了Class-File API,用于解析、生成和转换Java类文件。这一预览特性旨在取代JDK内部使用的ASM库,提供一个标准化的、与JDK同步的类文件处理工具。

背景

类文件是Java生态系统的核心,广泛用于编译器、框架和工具中。然而,处理类文件通常依赖第三方库(如ASM),这些库可能无法及时支持新的JDK版本,导致兼容性问题。

解决方案

Class-File API提供了一个标准化的接口,支持类文件的解析、生成和转换,与Java虚拟机规范保持一致。

示例

以下是一个示例,展示如何使用Class-File API读取类文件:

import java.lang.classfile.*;

public class ClassFileExample {
    public static void main(String[] args) throws Exception {
        ClassModel classModel = ClassFile.of().parse(ClassFileExample.class.getResourceAsStream("ClassFileExample.class"));
        System.out.println("Class Name: " + classModel.thisClass().name());
    }
}

好处

  • 标准化:提供与JDK同步的类文件处理工具。
  • 减少依赖:降低对第三方库的依赖。
  • 灵活性:支持类文件的解析、生成和转换。

注意事项

  • 需使用--enable-preview标志启用此预览特性。
  • 主要面向工具和框架开发者,普通开发者可能较少直接使用。

参考

7. 多文件源程序启动:JEP 458: Launch Multi-File Source-Code Programs

概述

JEP 458增强了Java Launcher,使其能够直接运行由多个Java源文件组成的程序,无需显式编译。这一特性扩展了Java 11中引入的单文件源代码运行功能(JEP 330)。

背景

在Java 11之前,运行Java程序需要先编译为类文件。对于小型项目或原型开发,这增加了复杂性。JEP 330允许运行单文件程序,但不支持多文件程序。

解决方案

JEP 458允许Java Launcher直接运行多个源文件,编译过程在内存中完成,无需生成类文件。

示例

假设有两个源文件:Main.javaHelper.java

  • Main.java
public class Main {
    public static void main(String[] args) {
        Helper.printHello();
    }
}
  • Helper.java
public class Helper {
    public static void printHello() {
        System.out.println("Hello, World!");
    }
}

运行命令:

java Main.java Helper.java

好处

  • 简化开发:无需显式编译,适合快速原型开发。
  • 灵活性:支持多文件程序,适用于小型项目。
  • 无缝过渡:便于从小型程序扩展到大型项目。

注意事项

  • 不支持通过“shebang”机制运行多文件程序。
  • 外部依赖的支持可能需要未来JEP扩展。

参考

8. 字符串模板(二次预览):JEP 459: String Templates (Second Preview)

概述

JEP 459引入了字符串模板(String Templates),允许在字符串中嵌入表达式,简化字符串构建。这一预览特性在Java 22中是第二次预览,但已在Java 23中被撤回,需注意其状态。

背景

传统的字符串构建方法(如字符串拼接或String.format)在复杂场景下显得繁琐且易出错。字符串模板提供了一种类似其他语言(如Python的f-strings)的解决方案。

解决方案

字符串模板使用STR处理器在字符串中嵌入表达式,支持单行和多行字符串。

示例

以下是一个示例,展示字符串模板的使用:

public class StringTemplateExample {
    public static void main(String[] args) {
        String name = "Alice";
        int age = 30;
        String message = STR."Hello, \{name}! You are \{age} years old.";
        System.out.println(message);
    }
}

对比
在Java 22之前,开发者需要使用字符串拼接:

String message = "Hello, " + name + "! You are " + age + " years old.";

新版本的代码更简洁,减少了拼接符号的使用。

好处

  • 可读性:字符串模板更直观,减少了样板代码。
  • 安全性:支持验证和转换,适合构建数据库查询等场景。
  • 灵活性:支持自定义模板处理器。

注意事项

  • 需使用--enable-preview标志启用此预览特性。
  • 该特性在Java 23中被撤回,未来版本可能会有重新设计。

参考

9. 向量 API(第七次孵化):JEP 460: Vector API (Seventh Incubator)

概述

JEP 460是Vector API的第七次孵化版本,旨在通过利用CPU的SIMD(Single Instruction, Multiple Data)指令提高数据密集型操作的性能。

背景

现代CPU支持SIMD指令,可以并行处理多个数据元素。然而,Java的传统循环无法充分利用这些指令。Vector API提供了一个高性能的向量化编程接口。

解决方案

Vector API允许开发者创建向量对象并执行向量化操作,编译器会将其优化为SIMD指令。

示例

以下是一个示例,展示如何使用Vector API进行数组操作:

import jdk.incubator.vector.*;

public class VectorExample {
    private static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;

    public static void main(String[] args) {
        float[] a = {1.0f, 2.0f, 3.0f, 4.0f};
        float[] b = {2.0f, 3.0f, 4.0f, 5.0f};
        float[] result = new float[4];

        FloatVector va = FloatVector.fromArray(SPECIES, a, 0);
        FloatVector vb = FloatVector.fromArray(SPECIES, b, 0);
        FloatVector vr = va.mul(vb);
        vr.intoArray(result, 0);

        System.out.println(Arrays.toString(result));
    }
}

好处

  • 高性能:利用SIMD指令显著提高计算性能。
  • 跨平台:支持优雅降级,确保在不支持SIMD的平台上仍能运行。
  • 灵活性:支持多种数据类型和操作。

注意事项

  • 需使用--add-modules jdk.incubator.vector启用此孵化特性。
  • 作为孵化特性,API可能在未来版本中发生变化。

参考

10. 流收集器:JEP 461: Stream Gatherers (Preview)

概述

JEP 461引入了Stream Gatherers,增强了Stream API,允许开发者定义自定义的中间操作,从而使流处理更加灵活。

背景

Stream API自Java 8引入以来,提供了丰富的中间操作(如mapfilter),但这些操作是固定的。开发者需要自定义操作时,往往需要复杂的嵌套或多步处理。

解决方案

Stream Gatherers通过Gatherers类提供接口,允许开发者定义自定义中间操作,支持更复杂的流处理逻辑。

示例

以下是一个示例,展示如何使用Stream Gatherers实现窗口操作:

import java.util.stream.*;

public class GathererExample {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
        stream.gather(Gatherers.windowFixed(2))
              .forEach(System.out::println);
    }
}

好处

  • 灵活性:支持自定义中间操作,扩展了Stream API的功能。
  • 可重用性:自定义操作可复用于多个流处理场景。
  • 支持无界流:适合处理无限流。

注意事项

  • 需使用--enable-preview标志启用此预览特性。
  • 作为预览特性,API可能在未来版本中调整。

参考

11. 结构化并发(二次预览):JEP 462: Structured Concurrency (Second Preview)

概述

JEP 462是Structured Concurrency的第二次预览,旨在通过将相关任务作为一个单元来简化并发编程,提高可靠性和可观察性。

背景

传统的并发模型(如ExecutorService)容易导致线程泄漏和取消延迟问题。Structured Concurrency通过结构化的方式管理任务,解决了这些问题。

解决方案

Structured Concurrency通过StructuredTaskScope类管理一组相关任务,确保它们作为一个单元被处理。

示例

以下是一个示例,展示如何使用Structured Concurrency:

import java.util.concurrent.*;

public class StructuredConcurrencyExample {
    public static void main(String[] args) throws Exception {
        try (var scope = new StructuredTaskScope<String>()) {
            var task1 = scope.fork(() -> "Task 1 completed");
            var task2 = scope.fork(() -> "Task 2 completed");
            scope.join();
            System.out.println(task1.get());
            System.out.println(task2.get());
        }
    }
}

好处

  • 简化并发:将相关任务作为一个单元管理。
  • 提高可靠性:减少线程泄漏和取消延迟。
  • 增强可观察性:通过线程转储更容易跟踪任务。

注意事项

  • 需使用--enable-preview标志启用此预览特性。
  • 作为预览特性,API可能在未来版本中调整。

参考

12. 隐式类与实例主方法(二次预览):JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview)

概述

JEP 463是Implicitly Declared Classes and Instance Main Methods的第二次预览,允许开发者编写不包含显式类声明的程序,并支持实例主方法,简化小型程序的编写。

背景

传统的Java程序需要显式声明公有类和静态主方法,这对初学者来说可能复杂。JEP 463的目标是降低学习曲线,简化程序结构。

解决方案

JEP 463允许省略类声明,编译器会自动生成隐式类,并支持非静态的实例主方法。

示例

以下是一个示例,展示隐式类和实例主方法:

void main() {
    System.out.println("Hello, World!");
}

对比
在Java 22之前,需要显式声明类和静态主方法:

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

新版本的代码更简洁,适合初学者。

好处

  • 简化代码:通过消除显式类声明的需求,减少了样板代码,使程序结构更简洁。例如,开发者可以直接编写 void main() 而无需定义类,这降低了代码复杂性。
  • 初学者友好:降低了学习 Java 的门槛,特别适合新手开发者编写小型程序,无需理解复杂的类和静态主方法概念。
  • 灵活性:支持更多编程模式,例如实例主方法,允许更灵活的程序设计。

这些好处旨在提升开发效率,特别是在教育场景或快速原型开发中。

注意事项

  • 这一特性是预览特性,需要使用 --enable-preview 标志启用,编译和运行时需添加此选项。
  • 作为预览特性,其设计和实现可能在未来版本中调整,开发者应关注后续 Java 版本的更新。

参考

13. 作用域值(二次预览):JEP 464: Scoped Values (Second Preview)

接下来是 JEP 464 的详细内容,这是 Java 22 的最后一个 JEP,涉及作用域值的第二次预览。

概述

JEP 464 引入了作用域值(Scoped Values),作为 Java 22 的第二次预览特性,旨在提供一种安全且高效的方式来在线程内和跨线程共享不可变数据。特别适合在虚拟线程环境下使用,解决了传统线程本地变量(ThreadLocal)的局限性。

背景

在 Java 中,线程本地变量(ThreadLocal)允许每个线程拥有独立的数据副本,但存在以下问题:

  • 可变性:ThreadLocal 变量是可变的,可能导致数据竞争和状态追踪困难。
  • 性能开销:当使用大量虚拟线程时,ThreadLocal 的内存和性能开销显著增加。
  • 复杂性:管理 ThreadLocal 的生命周期和清理较为复杂,尤其在并发场景下。

这些问题在现代高并发应用中尤为突出,特别是在虚拟线程(JEP 444)普及后,亟需一种更高效的解决方案。作用域值通过提供不可变数据共享,解决了这些问题。

解决方案

作用域值允许开发者定义 ScopedValue 实例,这些实例在线程内和跨线程共享,但只能在定义的作用域内访问。它们是不可变的,确保数据安全且高效。作用域值通过 tryWith 方法绑定到特定上下文,支持子线程继承,减少了数据复制的开销。

示例

以下是一个使用作用域值的示例,展示如何在主线程和子线程中共享数据:

import java.lang.ScopedValue;

public class ScopedValueExample {
    static final ScopedValue<String> USER = ScopedValue.newInstance();

    public static void main(String[] args) {
        USER.tryWith("Alice", () -> {
            System.out.println("User: " + USER.get());
            // 模拟子线程
            new Thread(() -> {
                System.out.println("Sub-thread User: " + USER.get());
            }).start();
        });
    }
}

在这个例子中,USER 被绑定到 “Alice”,在 tryWith 块内可用,主线程和子线程都可以访问,体现了作用域值的跨线程继承特性。

好处

  • 安全性:数据不可变,避免数据竞争和并发问题,确保线程安全。
  • 高效性:特别优化了虚拟线程的使用,减少内存开销,适合高并发场景。
  • 简洁性:通过作用域管理简化了数据共享逻辑,易于推理和维护。

这些好处使作用域值成为现代并发编程的强大工具,特别是在虚拟线程和结构化并发(JEP 462)结合使用时。

注意事项

  • 作为预览特性,需要使用 --enable-preview 标志启用,编译和运行时需添加此选项。
  • 作用域值仍在开发中,未来版本可能根据反馈进行调整,开发者应关注 Java 23 及后续版本的更新。

参考

14. 结语

Java 22 引入了多种新特性,这些特性从性能优化、语言简化到并发编程改进,极大地增强了 Java 的能力。这些特性旨在使 Java 更加高效、安全,同时为开发者提供更便捷的工具,尤其是在现代应用开发场景中。

以下是关键要点总结:

类别 代表性特性 主要优势
性能提升 G1 垃圾收集器的区域固定 (JEP 423), Vector API (JEP 460) 提高垃圾收集效率和数据处理性能
语言简化 未命名变量和模式 (JEP 456), 隐式类声明 (JEP 463) 减少样板代码,提升可读性和易用性
并发编程改进 结构化并发 (JEP 462), 作用域值 (JEP 464) 提供更好的并发任务管理和数据共享工具
本地代码交互 外部函数和内存 API (JEP 454) 增强与本地代码的交互能力

开发者应积极探索这些新特性,但需注意部分特性仍处于预览或孵化阶段,可能在未来版本中发生变化。例如,字符串模板 (JEP 459) 在 Java 23 中已被撤回,作用域值 (JEP 464) 仍在预览阶段,建议关注后续版本的更新。

通过跟踪这些最新进展,Java 开发者可以利用最新的工具和技术,构建出更高效、更可靠和更易维护的应用程序。

参考