Java 22于2024年3月19日发布,共有12个特性,本节就介绍其中相对重要的9个特性:
JEP 447:Statements before super(...) (Preview)super(...) 之前的语句(第一次预览)
JEP 454:Foreign Function & Memory API 外部函数和内存 API(转正)
JEP 458:Launch Multi-File Source-Code Programs 启动多文件源代码程序
JEP 459:String Templates (Second Preview) 字符串模板(第二次预览)
JEP 460:Vector API (Seventh Incubator) 向量API(第七轮孵化)
JEP 461:Stream Gatherers (Preview) 流收集器(第一次预览)
JEP 462:Structured Concurrency (Second Preview) 结构化并发(第二次预览)
JEP 463:Implicitly Declared Classes and Instance Main Methods (Second Preview)隐式声明的类和实例 main 方法(第二次预览)
JEP 464:Scoped Values (Second Preview) 范围值(第二次预览)
更多内容读者可自行阅读:OpenJDK Java 22文档
一、JEP 447:super(...) 之前的语句(第一次预览)
用过super调用父类的构造函数或用this调用另一个构造函数的同学都知道,super和this的调用必须是第一行(很不人性化),如果参数有问题,那就是在作无用功,比如官方给的例子:
public class PositiveBigInteger extends BigInteger {public PositiveBigInteger(long value) {super(value); // Potentially unnecessary workif (value <= 0)throw new IllegalArgumentException("non-positive value");}
}
这时候我们就不得不再写一个静态方法来校验参数:
public class PositiveBigInteger extends BigInteger {public PositiveBigInteger(long value) {super(verifyPositive(value));}private static long verifyPositive(long value) {if (value <= 0)throw new IllegalArgumentException("non-positive value");return value;}
}
在Java 22对这一“痛点”作了改进,并进行了首次预览,super和this的调用不再必须是第一行:
public class PositiveBigInteger extends BigInteger {public PositiveBigInteger(long value) {if (value <= 0)throw new IllegalArgumentException("non-positive value");super(value);}
}
二、JEP 454:外部函数和内存 API(转正)
该特性其实是由两个孵化API演变的:外部内存访问 API 和外部链接器 API,从孵化到转正共经历了8个Java版本。
外部内存访问 API 最初由 JEP 370 提出,并于 2019 年底作为孵化 API 针对 Java 14。
它在 Java 15 中由 JEP 383 和 Java 16 中的 JEP 393 重新孵化。
外部链接器 API 最初由 JEP 389 提出,并于 2020 年底针对 Java 16,也是一个孵化 API。
外部函数和内存(FFM)API通过 JEP 412 在 JDK 17 中孵化。
并通过 JEP 419 在 JDK 18 中重新孵化。
外部函数和内存(FFM)API最初是由JEP 424 (JDK 19)作为预览功能提出的。
随后由 JEP 434 (JDK 20)和JEP 442 (JDK 21)进行改进。
在JDK 22终于成为了正式特性。
这个在Java 19的时候介绍过,这里就不再赘述了
三、JEP 458:启动多文件源代码程序
在Java 11的时候有个单文件源代码启动的特性,就是如果运行只由一个文件组成的Java程序,就无需编译(javac命令),直接运行即可,如果是多个文件的话就需要单独编译才能运行。
Java 22引入了一个启动器,它支持运行由多个文件组成的程序,假设一个目录包含Prog.java和Helper.java两个文件:
// Prog.java
class Prog {public static void main(String[] args) { Helper.run(); }
}
// Helper.java
class Helper {static void run() { System.out.println("Hello!"); }
}
运行java Prog.java会在内存编译Prog并执行其main方法,这里Prog引用了Helper类,则启动器会在文件系统查找Helper.java文件然后内存编译。
四、JEP 459:字符串模板(第二次预览)
字符串模板最初是由 JDK 21 中的 JEP 430 作为预览功能提出的。
此JEP建议进行第二次预览。
本次和第一次预览相比基本没有变化,可以参考Java 21对这一特性的介绍。
五、JEP 460:向量API(第七轮孵化)
Vector API 最初由 JEP 338 提出,并作为孵化 API 集成到 JDK 16 中。
JEP 414(集成到 JDK 17 中)、JEP 417 (JDK 18)、JEP 426 (JDK 19)、JEP 438 (JDK 20) 和 JEP 448 (JDK 21) 提出了更多轮次的孵化。
此JEP建议进行第七轮孵化。
这个可以参考Java 16中对这一特性的介绍。
六、JEP 461:流收集器(第一次预览)
java 8引入了第一个专门为Lambda表达式设计的API:java.until.stream,不过这个API近几年来一直遭受批评,原因就是功能太少了,除了现有的filter、map、flatMap、mapMulti、distinct、sorted、peak、limit、skip、takeWhile和dropWhile之外,Java社区还希望看到window和fold等方法。
那么Java 22就来了,但是JDK开发人员没有将这些方法集成到JDK中,而是重新开发了一个API,允许开发人员编写任何中间流操作,这个API被称为“Stream Gatherers”,作为预览功能在Java 22中发布。
该API提供了一系列收集器操作,比如有windowFixed和windowSliding
void main() {List<String> list = List.of("a", "b", "c", "d", "e", "f", "g", "h");List<List<String>> windowFixed = list.stream().gather(Gatherers.windowFixed(3)).toList();System.out.println(windowFixed);//[[a,b,c],[d,e,f],[g,h]]
List<Integer> list1 = List.of(1, 2, 3, 4, 5);List<List<String>> windowSliding = list.stream().gather(Gatherers.windowSliding(3)).toList();System.out.println(windowSliding);//[[1,2,3],[2,3,4],[3,4,5]]
}
此外还有:fold、mapConcurrent、scan等操作就不演示了。
七、JEP 462:结构化并发(第二次预览)
结构化并发由 JEP 428 提出,并在 JDK 19 中作为孵化 API 提供。
它在 JDK 20 中由 JEP 437 重新孵化,并进行了小幅更新以继承范围值 (JEP 429)。
它首先在 JDK 21 中通过 JEP 453 进行了预览,并将 StructuredTaskScope
::
fork(...) 更改为返回 Subtask 而不是 Future。此JEP建议进行第二次预览。
本次没做任何更改,该特性Java 21中介绍过了,这里就不再赘述。
八、JEP 463:隐式声明的类和实例 main 方法(第二次预览)
JEP 445 提出了未命名类和实例主方法,在 JDK 21 中进行了预览。
反馈建议该功能应在 JDK 22 中第二次预览,并进行以下重大更改,因此修改了标题。
Java 22支持了更为灵活的程序启动协议,比如允许启动类的方法有public、protected权限,如果启动类包含参数方法则会选择有参数的,否则选择无参的main方法。
九、JEP 464:范围值(第二次预览)
范围值通过 JEP 429 在 JDK 20 中孵化。
并通过 JEP 446 在 JDK 21 中成为预览 API。
此JEP建议进行第二次预览。
本次也没作任何更改,该特性在Java 21介绍过了,这里不再赘述。