JDK23如约而至,数十种新玩法,你期待哪一种?

9 月 17 日,JDK23 它来了。

JDK23 并非长期支持版,下一个长期支持版是 JDK25,预计明年 9 月份发布。

和松哥一起来看下这次的 JDK23 都有哪些新特性~

一 Language Previews

➜ 在 instanceof 和 switch 中 支持原始类型(预览)

增强了模式匹配,扩展 instanceofswitch 以支持所有原始类型。这是一项预览语言特性。

参见 JEP:455,https://openjdk.org/jeps/455

➜ 模块导入声明(预览)

增强 Java 编程语言,使其能够简洁地导入模块导出的所有包。这简化了模块库的重用。这是一项预览语言特性。

类似这样去导入模块:

1
2
import module java.base;
import module java.sql;

但是如果同一个模块中出现了同名的类,那么就必须恢复到之前的写法,显式导入了。

参见 JEP476,https://openjdk.org/jeps/476

➜ 灵活的构造函数体(第二次预览)

在 Java 编程语言中的构造函数中,允许在显式的构造函数调用之前出现语句,即 super(..)this(..) 之前允许出现其他代码。这些语句不能引用正在构造的实例,但它们可以初始化类的属性。在调用另一个构造函数之前初始化字段,这样当方法被覆盖时,可以使类更可靠。这是一项预览语言特性。

松哥给大家举一个使用场景,例如下面两个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Animal {

Animal() { overriddenMethod(); }

void overriddenMethod() { System.out.println("hello"); }

}
public class Dog extends Animal {

final Integer x;

Dog(int x) {
this.x = x;
super();
}

@Override
void overriddenMethod() { System.out.println(x.toString()); }

}

按照之前的写法,上面这段代码编译会出错。因为在 super() 之前出现了其他代码。但是如果不在 super 之前初始化 x,那么当初始化 Dog 的时候,就会出错,因为初始化 Dog 会调用 Animal 的构造器,进而调用到 overriddenMethod 方法,而该方法在 Dog 中被重写了,重写后的方法用到了 x 这个变量…不过,以后这个问题就可以解决了。

参见 JEP482,https://openjdk.org/jeps/482

➜ 隐式声明的类和实例主方法(第三次预览)

以前我们写 main 方法可能是这样:

1
2
3
4
5
6
public class HelloWorld {

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

以后可以写成这个样子了:

1
2
3
void main() {
println("Hello, World!");
}

这里连类都没有了,隐式声明类继承自 Object,不实现接口,并且不能在源代码中按名称引用。此外,实例主方法也不再强制要求它们是 static 或 public 的,并且不带参数的方法也可以作为有效的程序入口点。

参见 JEP477,https://openjdk.org/jeps/477

二 Libraries Previews

➜ 类文件 API(第二次预览)

提供解析、生成和转换 Java 类文件的标准 API。这是一项预览 API。

参见 JEP466,https://openjdk.org/jeps/466

➜ 流收集器(第二次预览)

增强 Stream API 以支持自定义中间操作,让流操作更加灵活。这是一项预览 API。

参见 JEP473,https://openjdk.org/jeps/473

➜ 结构化并发(第三次预览)

通过引入结构化并发 API 简化并发编程。结构化并发将不同线程中的相关任务组视为单个工作单元,从而简化错误处理和取消,提高可靠性,并增强可观察性。这是一项预览 API。

参见 JEP480,https://openjdk.org/jeps/480

➜ 作用域值(第三次预览)

引入作用域值,它使得方法能够在线程内及其调用者之间共享不可变数据,以及与子线程共享。作用域值比线程局部变量更容易理解。当与虚拟线程(JEP 444)和结构化并发(JEP 480)一起使用时,它们还具有更低的空间和时间成本。这是一项预览 API。

参见 JEP481,https://openjdk.org/jeps/481

➜ 向量 API(第八次孵化)

引入一种 API,用于表达在运行时可靠地编译为受支持 CPU 架构上的最佳向量指令的向量计算,从而实现优于等效标量计算的性能。

参见 JEP469,https://openjdk.org/jeps/469

三 性能

可以在 Oracle JDK 中使用 Graal JIT

Oracle GraalVM JIT 编译器(Graal JIT)现在作为 Oracle JDK 的一部分可用。这种集成为开发人员和系统管理员提供了更多选项,以帮助微调和提高应用程序的峰值性能。

不过这个特性需要手动启用:

-XX:+UnlockExperimentalVMOptions -XX:+UseGraalJIT

如果在 JVM 启动时不传递这些参数,则 Oracle JDK 的默认 JIT(C2)将照常运行。

➜ ZGC:默认的分代模式

将 Z 垃圾收集器 (ZGC) 的默认模式切换为分代模式。弃用非分代模式,计划在未来的版本中将其移除。

参见 JEP474,https://openjdk.org/jeps/474

四 工具

➜ Markdown 文档注释

允许 JavaDoc 文档注释以 Markdown 而非仅 HTML 和 JavaDoc @ 标签的混合形式编写。

参见 JEP467,https://openjdk.org/jeps/467

五 管理

➜ 弃用 sun.misc.Unsafe 中的内存访问方法

弃用 sun.misc.Unsafe 中的内存访问方法以备在未来的版本中移除。这些不受支持的方法已被标准 API 取代,即 VarHandle API(JEP 193, JDK 9)和外部函数以及内存 API(JEP 454, JDK 22)。我们强烈鼓励库开发人员从 sun.misc.Unsafe 迁移到支持的替代品,以便应用程序可以顺利迁移到现代 JDK 版本。

参见 JEP471,https://openjdk.org/jeps/471

六 撤回的 JEP

➜ 字符串模板

字符串模板首次在 JDK21 (JEP430) 中预览,并在 JDK22 (JEP 459) 中再次预览。经过反馈和广泛讨论,我们得出结论,该特性在当前形式下不适合。目前还没有更好的设计共识,因此我们暂时撤回了该特性,JDK23 将不包含它。


七 重要更改和信息

javac 中默认禁用注解处理 ( JDK-8321314)

从 JDK23 开始,只有在显式配置注解处理或在 javac 命令行上显式请求运行注解处理时,才会运行注解处理。这和当前的默认行为不同,现有默认行为是在没有显式注解处理相关选项的情况下,通过搜索类路径中的处理器来运行注解处理。

最后再做一个小小调研,你目前使用哪个版本的 JDK?(以下选项只列出来 LTS 版本)