ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Java 25新增的特性

Java 25新增的特性 Java 25新增的特性本文由博主提供思路、结构、行文风格AI负责搜索资料、生成内容博主再进行修订、验证。文中的源代码均已通过验证。目录Java 25新增的特性引言1. 紧凑源文件与实例main方法 (Compact Source Files and Instance main Methods) [JEP 512]2. 模块导入声明 (Module Import Declarations) [JEP 511]3. 灵活构造函数体 (Flexible Constructor Bodies) [JEP 513]4. 作用域值 (Scoped Values) [JEP 506] - 暂未修订Java 25的其他主要改进提前编译命令行人机工程学 (Ahead-of-Time Command-Line Ergonomics) [JEP 514]提前编译方法分析 (Ahead-of-Time Method Profiling) [JEP 515]紧凑对象头 (Compact Object Headers) [JEP 519]密钥派生函数API (Key Derivation Function API) [JEP 510]推荐阅读引言Java 25于2025年9月发布是继Java 21之后的又一个长期支持(LTS)版本。Java 25包含18个JEP其中多项语言特性在经过多轮预览后正式定型。语言层面的永久特性包括紧凑源文件与实例main方法(JEP 512)、模块导入声明(JEP 511)、灵活构造函数体(JEP 513)。核心库层面正式定型的有作用域值(JEP 506)。此外紧凑对象头等性能改进也从实验性转为产品级特性。本文将介绍这些正式特性并提供可运行的示例代码。1. 紧凑源文件与实例main方法 (Compact Source Files and Instance main Methods) [JEP 512]紧凑源文件允许编写不包含类声明的Java程序并支持将main方法定义为实例方法。它的核心目标是让初学者和脚本编写者能用更少的样板代码写Java程序同时确保这些代码可以无缝地演进为普通的Java类。该特性从JDK 21开始经过四轮预览最终在JDK 25正式定型。适用场景大量独立的小程序、脚本或原型。传统Java程序的Hello World写法public class HelloWorld { public static void main(String[] args) { System.out.println(Hello, World!); } }在Java 25中可以直接写void main() { IO.println(Hello, World!); }这里有几个关键变化隐式声明的类当你在源文件里直接写方法(比如main)编译器会自动把这些内容归属于一个隐式的、未命名的顶层类。你不再需要显式地写出public class ...。实例main方法main方法不再必须是static的。它可以是实例方法Java启动器会在调用它之前自动创建类的实例。新的IO类Java 25在java.lang包中新增了IO类提供了println、print、readln等静态方法。它基于System.out和System.in实现。核心库的隐式导入紧凑源文件会自动访问java.base模块导出的所有公共顶层类这意味着你可以直接使用List、ArrayList、File等类而不用写import java.util.*;这样的语句。注意虽然IO类本身因为位于java.lang包而被隐式导入但它的静态方法不会被自动导入。你仍然需要写IO.println(...)而不能直接写println(...)。官方的说明是这样做是为了让紧凑源文件在转化为常规类时过渡更平稳避免引入额外的静态导入要求。可运行示例(需保存为CompatSourceFileTest.java)String greeting() { // 实例方法 return Hello, World!; } static String sayHi() { // 静态方法 return Hi; } void main() { // 这个是实例方法而不是static方法 IO.println(Hello World); IO.println(greeting()); // 无需创建对象 IO.println(sayHi()); // 无需创建对象 // 注意因为是紧凑源文件会自动导入java.base模块 // 因此无需import java.util.*就可运行如下代码 ListString list new ArrayListString(); list.add(a); IO.println(list.get(0)); }补充说明紧凑源文件代表的是一个独立的、完整的程序入口而不是一个可被其他代码复用的库组件。当创建一个紧凑源文件的时候请注意:每个紧凑源文件都包含一个 main 方法代表一个程序。它不应该被其他类引用因此不能用来定义 API。虽然它不能使用package但是依然可以把它放在不同的子目录中。但在IDEA中运行该文件其生成的.class文件会被强制创建在项目的根目录而非你所在的包路径下。紧凑源文件(Compact Source File)被设计为自动导入 java.base 模块的所有公开类。java.util 包属于 java.base 模块。2. 模块导入声明 (Module Import Declarations) [JEP 511]模块导入声明允许通过一条import module语句导入整个模块导出的所有包无需逐包编写import语句。需要注意的是这是新增的一种可选语法而不是对旧语法的替换。你仍然可以继续使用import java.util.*;这种传统写法。例如原来需要三条按需导入声明来引入java.util、java.util.function和java.util.stream这三个包import java.util.*; import java.util.function.*; import java.util.stream.*;现在只需一条模块导入声明即可import module java.base;import module java.base会导入java.base模块导出的所有包。如果需要使用SQL相关的API还可以再添加import module java.sql;它会同时导入java.sql包以及java.sql模块间接导出的包。需要注意的是使用模块导入声明时如果不同包中存在同名的类可能会导致编译错误此时可以使用单类型导入声明来消除歧义。可运行示例(需保存为ModuleImportDeclarationsTest.java)import java.util.stream.Collectors; import java.util.stream.Stream; public class ModuleImportDeclarationsTest { void main() { var fruits Stream.of(apple, banana, cherry) .map(String::toUpperCase) .collect(Collectors.toList()); IO.println(fruits); } }3. 灵活构造函数体 (Flexible Constructor Bodies) [JEP 513]在Java 25之前构造函数中super()或this()调用必须是第一条语句。灵活构造函数体解除了“构造函数中第一条语句必须是 super() 或 this()”的限制。灵活构造函数体将构造函数体分为两个阶段序言(prologue)在父类构造器调用前执行(即super(...)与this(...)调用之前)尾声(epilogue)在其后执行(即super(...) 或 this(...) 调用之后的所有代码)。序言中可以执行参数校验、参数准备和字段初始化等操作。通过这种方式即使方法被重写也能确保对象在对外可见前已经被安全初始化。public class FlexibleConstructorBodyTest { void main() { try { new PositiveNumber(-1); } catch (IllegalArgumentException e) { IO.println(创建失败: e.getMessage()); } var num new PositiveNumber(42); IO.println(创建成功: num.value()); } class PositiveNumber extends Number { private final int value; PositiveNumber(int value) { // 序言在 super() 之前执行 // Java 25 之前这里不能写任何语句必须先调用 super() if (value 0) { throw new IllegalArgumentException(value must be positive); } super(); // 显式调用父类构造器(Number 的无参构造) // 尾声在 super() 之后执行 this.value value; } int value() { return value; } Override public int intValue() { return value; } Override public long longValue() { return value; } Override public float floatValue() { return value; } Override public double doubleValue() { return value; } } }4. 作用域值 (Scoped Values) [JEP 506] - 暂未修订作用域值允许方法在同一线程内与其被调用者以及子线程之间共享不可变数据是线程局部变量(ThreadLocal)的现代替代方案。与ThreadLocal相比作用域值具有以下优势数据不可变避免了并发风险生命周期由作用域限定超出作用域后数据自动不可访问与虚拟线程配合使用时资源开销更低。官方说明指出作用域值“更容易推理并且具有更低的空间和时间成本”。可运行示例(需保存为ScopedValueDemo.java)import java.lang.ScopedValue; static final ScopedValueString USER ScopedValue.newInstance(); void main() { ScopedValue.where(USER, Alice).run(() - { IO.println(当前用户: USER.get()); callService(); }); } static void callService() { IO.println(服务层获取用户: USER.get()); }运行方式java ScopedValueDemo.java程序输出当前用户: Alice 服务层获取用户: AliceScopedValue.where(USER, Alice).run(...)将USER绑定到值Alice并在该作用域内执行代码。在作用域内调用的任何方法都可以通过USER.get()获取该值无需通过方法参数逐层传递。Java 25的其他主要改进提前编译命令行人机工程学 (Ahead-of-Time Command-Line Ergonomics) [JEP 514]Project Leyden是Java 25中影响最“出圈”的改进方向它直接回应了Java长期以来在云原生和Serverless场景下的痛点——启动慢、预热时间长。JEP 514简化了创建AOT缓存的操作。在JDK 24中生成AOT缓存需要运行java两次(先record再create)。JDK 25引入了-XX:AOTCacheOutput选项只需一条命令即可完成记录和缓存创建java -XX:AOTCacheOutputapp.aot -cp app.jar com.example.App后续生产运行时指定缓存文件即可享受加速java -XX:AOTCacheapp.aot -cp app.jar com.example.App提前编译方法分析 (Ahead-of-Time Method Profiling) [JEP 515]JEP 515将前一次运行的方法执行分析数据存入AOT缓存。HotSpot JVM启动时即可使用这些数据JIT编译器无需等待运行时收集profile就能立即生成高效的本地代码从而“消除典型的预热期”。紧凑对象头 (Compact Object Headers) [JEP 519]Java 25将HotSpot JVM中对象头的大小从96到128位减少到64位(64位架构下)这可以减少堆内存占用并提高缓存局部性。该特性在JDK 24中为实验性特性在JDK 25中转为产品级特性。通过JVM参数-XX:UseCompactObjectHeaders启用(不再需要-XX:UnlockExperimentalVMOptions)。密钥派生函数API (Key Derivation Function API) [JEP 510]密钥派生函数API提供了标准的密钥派生函数接口用于从主密钥安全地派生出多个子密钥。该API在JDK 24中作为预览特性引入在JDK 25中正式定型。它是Java为后量子密码学做准备的关键构件之一。推荐阅读Java 17 新增的特性Java 21新增的特性
返回列表