Java 22新特性概览 -- 知识铺
1. 引言
在本教程中,我们将深入探讨最新的 Java 版本 Java 22,该版本现已正式发布。
让我们来谈谈作为此版本的一部分对 Java 语言的所有新更改。
2.1. 未命名的变量和模式 – JEP 456
我们经常定义代码中未使用的临时变量或模式变量。通常情况下,这是由于语言限制,禁止删除它们或引入副作用。异常、开关模式和 Lambda 表达式是我们在特定范围内定义变量或模式的示例,但我们从未使用过它们:
|
|
未命名变量 (_) 在这种情况下是完美的,并且使变量的意图明确无误。它们不能在代码中传递,也不能使用或分配值。让我们重写前面的例子:
|
|
2.2. super() 之前的语句 – JEP 447
很长一段时间以来,Java 不允许我们在子类的构造函数中调用 super() 之前放置任何语句。假设我们有一个 Shape 类系统和两个类,Square 和 Circle,从 Shape 类扩展而来。在子类构造函数中,第一个语句是对 super() 的调用:
|
|
当我们在调用 super() 之前执行某些验证时,这很不方便。在此版本中,解决了以下问题:
|
|
我们应该注意,我们放在 super() 之前的语句不能访问实例变量或执行方法。我们可以用它来执行验证。此外,我们可以在调用基类构造函数之前使用它来转换派生类中接收的值。
这是预览 Java 功能。
3. 字符串模板 – JEP 459
Java 22 引入了 Java 流行的字符串模板功能的第二个预览版。字符串模板允许嵌入文本以及表达式和模板处理器,以生成专用结果。它们也是其他弦乐合成技术更安全、更有效的替代品。
在此版本中,字符串模板继续处于预览状态,自首次预览版以来对 API 进行了小幅更新。对模板表达式的键入进行了新的更改,以在模板处理器中使用相应 process() 方法的返回类型。
4. 隐式声明的类和实例主方法 – JEP 463
Java 最终支持编写程序,而无需使用其标准模板定义显式类或 main 方法。我们通常是这样定义一个类的:
|
|
开发人员现在可以简单地创建一个带有 main() 方法定义的新文件,如下所示并开始编码:
|
|
我们可以使用其文件名对其进行编译。未命名的类驻留在未命名的包中,该包驻留在未命名的模块中。
5. 图书馆
Java 22 还带来了新的库并更新了一些现有的库。
5.1. 外部函数和内存 API – JEP 454
Java 22 在经过几次孵化器迭代后最终确定了 Foreign Function and Memory API,作为 Project Loom 的一部分。此 API 允许开发人员调用外部函数,即 JVM 生态系统外部的函数,并访问 JVM 外部的内存。
它允许我们访问其他运行时和语言的库,这是 JNI(Java Native Interface)所做的,但效率更高、性能提升和安全性更高。此 JEP 为在运行 JVM 的所有平台上调用本机库提供了更广泛的支持。此外,该 API 内容广泛且更具可读性,并提供了跨多种内存类型(例如堆内存和瞬态内存)对无限大小的结构化和非结构化数据进行操作的方法。
我们将对 C 的 strlen() 函数进行本机调用,以使用新的 Foreign Function and Memory API 计算字符串的长度:
|
|
5.2. 类文件 API – JEP 457
类文件 API 标准化了读取、解析和转换 Java .class 文件的过程。此外,它的目标是最终弃用 JDK 的第三方 ASM 库的内部副本。
类文件 API 提供了几个强大的 API,用于有选择地转换和修改类中的元素和方法。举个例子,让我们看看如何利用 API 删除以 test_ 开头的类文件中的方法:
|
|
此代码分析源类文件的字节,并通过仅采用满足给定条件的方法(由 MethodModel 类型表示)来转换它们。可以验证生成的类文件,该文件省略了原始类的 test_something() 方法。
5.3. 流收集器 – JEP 461
JEP 461 通过 Stream::gather(Gatherer) 在 Streams API 中引入了对自定义中间操作的支持。开发人员长期以来一直希望支持其他操作,因为内置流中间操作有限。通过此增强功能,Java 允许我们创建自定义中间操作。
我们可以通过在流上链接 gather() 方法并为其提供 Gatherer 来实现这一点,Gatherer 是 java.util.stream.Gatherer 接口的一个实例。
让我们使用 Stream 收集器使用滑动窗口方法将元素列表分组为 3 个:
|
|
作为此预览功能的一部分,有五个内置收集器:
- 倍
- map并发
- 扫描
- windowFixed
- 窗口滑动
此 API 还使开发人员能够定义自定义 Gatherer。
5.4. 结构化并发 – JEP 462
结构化并发 API 是 Java 19 中的孵化器特性,在 Java 21 中作为预览特性引入,并在 Java 22 中返回,没有任何新变化。
此 API 的目标是在 Java 并发任务中引入结构和协调。
结构化并发 API 旨在通过引入一种编码风格模式来改进并发程序的开发,该模式旨在减少并发编程的常见陷阱和缺点。
此 API 简化了错误传播,减少了取消延迟,并提高了可靠性和可观察性。
5.5. 作用域值 – JEP 464
Java 21 引入了作用域值 API 作为预览功能以及结构化并发功能。此 API 在 Java 22 中移动到第二个预览版中,没有任何更改。
作用域值允许在线程内和线程之间存储和共享不可变数据。作用域值引入了一种新类型 ScopedValue<>。我们写入一次值,它们在整个生命周期中保持不变。
Web 请求和服务器代码通常使用 ScopedValues。它们被定义为公共静态字段,并允许在方法之间传递数据对象,而无需定义为显式参数。
在以下示例中,让我们看看如何对用户进行身份验证,并将其上下文存储为跨多个实例的 ScopedValue:
|
|
唯一用户的多次登录尝试将用户信息范围限定为其唯一线程:
|
|
5.6. Vector API(第七孵化器)– JEP 460
Java 16 引入了 Vector API,Java 22 带来了第七个孵化器。此更新提供了性能改进和次要更新。以前,矢量访问仅限于堆 MemorySegments,这些 MemorySegments 由字节数组提供支持。它们现在已更新为由一系列基元元素类型提供支持。
此更新是低级别的,不会以任何方式影响 API 的使用。
Java 22 更新了 Java 构建文件的工具。
6.1. 多文件源程序 – JEP 458
Java 11 引入了执行单个 Java 文件,而无需使用 javac 命令显式编译它。这非常有效和快速。缺点是,当存在依赖的 Java 源文件时,我们无法发挥其优势。
从 Java 22 开始,我们终于可以运行多文件 Java 程序了:
|
|
我们可以直接运行 MainApp,而无需显式运行 javac:
|
|
请记住以下几点:
- 当类分散在多个源文件中时,无法保证编译顺序
- 编译主程序引用其类的.java文件
- 不允许在源文件中重复类,并且会出错
- 我们可以传递 –class-path 选项来使用预编译的程序或库
7. 性能
Java 的这次迭代带来的性能更新是对 G1 垃圾回收器机制的增强。
7.1. G1 垃圾回收器的区域固定 – JEP 423
固定是通知 JVM 的底层垃圾回收器不要从内存中删除特定对象的过程。不支持此功能的垃圾回收器通常会暂停垃圾回收,直到指示 JVM 释放关键对象。
这是一个主要见于JNI关键部分区域的问题。垃圾回收器中缺少固定功能会影响其在 JVM 中的延迟、性能和整体内存消耗。
在 Java 22 中,G1 垃圾回收器终于支持区域固定。这样,Java 线程就无需在使用 JNI 时暂停 G1 GC。
8. 结论
Java 22 为 Java 带来了大量的更新、增强和新的预览功能。
像往常一样,所有代码示例都可以在 GitHub 上找到_._
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek001/post/20240507/Java-22%E6%96%B0%E7%89%B9%E6%80%A7%E6%A6%82%E8%A7%88--%E7%9F%A5%E8%AF%86%E9%93%BA/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com