百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

Java 21:有什么新变化?

wptr33 2024-12-13 16:38 24 浏览

【CSDN 编者按】这篇文章详细介绍了Java 21 的新特性和改进。Java 21是新的长期支持(LTS)版本,其中包括了15个Java增强提案(JEPs)。其中最重要的特性之一是虚拟线程的最终化,这些线程的创建和调度成本较低,使并发应用程序的编写变得更容易。文章还介绍了一些新的预览特性,如字符串模板(用于字符串插值)、序列化集合(增强了 Java 的集合 API)、未命名模式和变量、未命名类和实例 main 方法等。此外,还讨论了从预览状态转变为标准特性的一些功能,如记录模式、switch 的模式匹配和虚拟线程等。文章还提到了性能和安全等方面的改进。

原文链接:https://www.loicmathieu.fr/wordpress/en/informatique/java-21-quoi-de-neuf/

未经允许,禁止转载!


作者 | LOIC 译者 | 明明如月
责编 | 夏萌
出品 | CSDN(ID:CSDNnews)

现在 Java 21 已经功能完备,并进入了 Rampdown 第二阶段,本文将深入介绍这个新版本的主要功能。

Java 21 是新推出的长期支持版本(Long Term Support ,LTS),将会提供两年的技术支持。其中包含的 JEP(Java 增强提案)数量不下于 15 个,这个版本功能非常丰富。最引人注目的是虚拟线程已经完全实现了!作为轻量级线程,虚拟线程的创建和调度成本低,让编写并发应用程序变得更简单。尽管整个生态系统对虚拟线程的支持还需时日,虚拟线程的引入无疑将确保 Java 在内存受限环境中高并发应用程序的领先地位。

JEP 430 – 字符串模板(预览)

字符串插值在多数编程语言中已得到支持。这一特性是指一个结合了表达式和文本字面量的字符串字面量。

例如,在 Kotlin 中,表达式 "$x plus $y equals ${x + y}" 包含了 $x$y${x + y},这些表达式会被转换为相应的文本值。这一过程称为字符串内的插值,它基于变量并允许变量间的运算,例如执行加法运算。

不过,因为在构造最终字符串的过程中无法进行验证或清洗,字符串插值作为全局特性会带来一些风险。例如,它可能增加了受到 SQL 或 JavaScript 注入攻击的风险。

在 Java 中,字符串模板是通过模板处理器来实现,该处理器能够在插值过程中提供验证和清理操作。

模板处理器接受一个模板,并将其插值到特定类型的对象,如String,或者一个 PreparedStatement,或者一个 JSONObject 等。支持多个处理器,每个处理器都可执行验证步骤(如果需要)。

下面的示例展示了如何使用没有特定验证的字符串模板 STR,作为字符串连接的替代方法:

String firstName = "Lo?c";String lastName = "Mathieu";String helloWorld = STR."Hello \{firstName} \{lastName}";

在 Java 中,表达式由 \{expression} 定义,并通过名为 FMT 的模板处理器调用,这是先前通过静态导入导入的 StringTemplate 接口的常量。

关于表达式格式的选择有很多不同的观点。许多库选择使用 $、# 或 {} 作为表达式分隔符,因此选择了一个字符串模板之外无效的格式:String s = "Hello \{firstName} \{lastName}" 是无法编译的。这是字符串模板与普通字符串的不同之处。

标准库提供了三个模板处理器:

  • RAW:不对字符字符串进行插值的处理器,允许低级操作。

  • STR:通过简单连接将字符字符串插入到另一个字符字符串的处理器。

  • FMT:通过 Formatter 等手段,允许格式化表达式的处理器,例如 FMT."%05d\{x} + %05d\{y} = %05d\{x + y}"

你还可以通过实现 StringTemplate.Processor 接口来创建自定义的处理器。

更多详情,请参阅:JEP 430 。

JEP 431 – 顺序集合

Java 21 在集合 API 中引入了一个创新性的扩展,这样的扩展在许多先前的版本中尚未出现过。

在过去的 Java 版本中,集合缺乏代表有序元素序列的类型。然而,Java 21 通过引入了 SequencedCollectionSequencedSet SequencedMap 接口,弥补了这一不足。这些接口定义了在集合开头或结尾处添加、修改或删除元素的方法,以及以逆序方式遍历集合的功能。

下面展示了 SequencedCollection 接口:

interface SequencedCollection<E> extends Collection<E> { SequencedCollection<E> reversed(); void addFirst(E); void addLast(E); E getFirst(); E getLast(); E removeFirst(); E removeLast();}

reversed() 方法将返回一个集合的逆序视图,并且对原始集合所做的任何更改都会反映在这个逆序视图上。

SequencedSet 则是一个继承了 SequencedCollection 的集合类型,以下是它的接口定义:

interface SequencedSet<E> extends Set<E>, SequencedCollection<E> { SequencedSet<E> reversed();}

此外,SequencedMap 作为一种条目有序的映射,其接口如下所示:

interface SequencedMap<K,V> extends Map<K,V> { SequencedMap<K,V> reversed(); SequencedSet<K> sequencedKeySet(); SequencedCollection<V> sequencedValues(); SequencedSet<Entry<K,V>> sequencedEntrySet(); V putFirst(K, V); V putLast(K, V); Entry<K,V> firstEntry(); Entry<K,V> lastEntry(); Entry<K,V> pollFirstEntry(); Entry<K,V> pollLastEntry();}

这些新接口已经完美融合到现有的 Collection API 类层次结构中。

值得一提的是,一些在 Collection API 中广泛使用的实现,如 ArrayListLinkedListLinkedHashMapLinkedHashSet,现在已经支持顺序集合特性。

有关更多详细信息,请参阅 JEP 431。

JEP 443 – 未命名模式与变量预览

Java 语言引入了一项新特性,即允许使用下划线 _ 来表示未命名模式或变量。这一特性旨在用 _ 标识无效或不需要使用的模式或变量,编译器将确保这样的变量真实地未被使用,因为它们是无名的。

在 Java 的模式匹配过程中,_ 可作为未命名模式使用,如 instanceof Point(_, int y),或作为未命名模式变量使用,例如 instanceof Point(int _, int y) case Box(GreenBall _)

下划线 _ 还可以表示不可读写的未命名变量。由于它们没有名称,在同一作用域中可以多次使用此类未命名变量。

未命名变量可以在以下场合使用:

  • 作为语句内部的局部变量;

  • 用于 try-with-resource 结构的资源;

  • 在 for 循环(包括基本和增强)的头部;

  • 作为 catch 块的异常参数;

  • 作为 lambda 表达式的参数。

以下是 JEP 443 中的示例代码:

// 增强 for 循环int acc = 0;for (Order _ : orders) { if (acc < LIMIT) {  ... acc++ ... }}
// 块语句Queue<Integer> q = ... // x1, y1, z1, x2, y2, z2, ...while (q.size() >= 3) { var x = q.remove(); var y = q.remove(); var _ = q.remove(); ... new Point(x, y) ...}
// catch 块String s = ...try { int i = Integer.parseInt(s); ... i ...} catch (NumberFormatException _) { System.out.println("Bad number: " + s);}
// try-with-resourcestry (var _ = ScopedContext.acquire()) { ... no use of acquired resource ...}
// lambda 参数stream.collect(Collectors.toMap(String::toUpperCase, _ -> "NODATA"))

虽然这个特性在表面上看似微小,但实际上它备受期待,能够通过清晰标识不应使用的变量,极大地提高代码的可读性,并避免潜在的错误。不过,目前还不能将 _ 用作重载方法的参数。

更多详细信息,请参阅 JEP 443。

JEP 445: 未命名类与实例 main 方法(预览版)

这一新特性旨在让 Java 在编写简单场景如基础 main 方法时变得更加容易学习和掌握。

以 Java 中经典的 "Hello World" 示例为例:

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

要输出 "Hello World" 到控制台,你需理解有关类、方法、可见性以及 static 修饰符的原则,还要掌握 Java main 方法的具体签名,即作为程序入口点的执行方法。

第一项更改:允许非 static(实例方法)、非公共的无参数 main 方法:

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

第二项更改:引入未命名的类:

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

未命名类位于 .class 文件中,没有类声明,不能被其他类引用,但可包含方法和字段。它被归属于一个未命名的包。

这两项新特性主要针对学习 Java 的开发人员。通过减少编写 Java 程序入口点所需的额外步骤,大大便利了中小型 Java 程序的开发。

此外,关于 System.out.println()(以及控制台读取)和可能的简化也在讨论之列。未来的 Java 版本可能会在这方面进一步的简化。

更多详细信息,请参阅 JEP 445。

新增的标准功能

以下功能已从预览(或孵化模块)阶段转型为正式标准功能:

  • JEP 440 – 记录模式:通过记录模式优化 Java 的模式匹配,能将记录细分为各个属性。

  • JEP 441 – switch 模式匹配:允许基于变量的类型(包括枚举、记录和数组)执行 switch 操作,并从中提取相应类型的局部变量。

  • JEP 444 – 虚拟线程:也可称为绿色线程或轻量级线程,它们的创建和调度成本较低,简化了并发应用程序的编写。

仍在预览阶段的功能

以下功能依然处于预览(或孵化模块)状态:

  • JEP 442 – 外部函数和内存 API(第三次预览):该功能已根据预览反馈进行改进,现通过新的 Arena API 来管理本地内存段。

  • JEP-448 – 向量 API:该功能正处于第六次孵化,新版本中包括了错误的修正以及性能的提升。

  • JEP 446 – 作用域值(预览):该功能允许在线程内部及线程之间共享不可变数据,现处于预览阶段。

  • JEP 453 – 结构化并发(预览):这是一种全新的 API,它通过将多个并发任务整合为单一处理单元来简化多线程代码的编写,目前仍处于预览阶段。

杂项

JDK 的各种补充:

  • Character.isEmoji()Character.isEmojiPresentation()Character.isEmojiModifier()Character.isEmojiModifierBase()Character.isEmojiComponent()Character.isExtendedPictographic()

  • Math.clamp()StrictMath.clamp():将一个值限制在最小值和最大值之间。

  • StringBuilder.repeat():将字符或字符串拼接特定次数。

  • HttpClient 现在实现了 AutoCloseable,因此可以在 try-with-resources 块中更轻松地使用。

  • Locale.availableLocales():返回已安装的区域设置列表。

  • Collections.shuffle(List, RandomGenerator):使用 RandomGenerator 对列表的元素进行随机排列。

  • String.splitWithDelimiters()Pattern.splitWithDelimiters():使用分隔符来分割字符串。

所有新的 JDK 21 API 可以在 Java 版本年鉴 - Java 21 中的新 API 中找到。

内部变化、性能和安全性

ZGC 垃圾收集器现已升级为分代收集方式,以便根据对象的年龄将堆划分为多个区域。要激活这项功能,可使用命令行选项 -XX:+ZGenerational。ZGC 的设计初衷是支持极大的堆(数太字节)并实现非常低的暂停时间(毫秒级)。采用分代堆策略使其能在更低资源消耗下支持不同工作负载。详细信息可参考 JEP 439。

在安全领域,Java 已经引入了密钥封装机制(KEM),这是一种利用公钥加密来保护对称密钥的方法。详细信息可参考 JEP 452。

Windows 将在未来的版本中废弃 32 位端口的 x86 CPU。Windows 10 将成为支持 32 位架构的最后一个版本,其到期日期定于 2025 年 10 月。简化 Open JDK 的构建并降低维护成本的方式是弃用并最终移除 Windows 32 位端口。详细信息可参考 JEP 449。

目前,Java 动态代理加载已被标记为废弃。如果使用该功能,JVM 日志将显示警告。Java 代理在程序启动时的加载仍然受支持,但程序启动后的动态加载已被废弃。此举旨在增强 JVM 的完整性,因为代理可修改应用程序代码,运行时加载它可能带来安全风险。详细信息可参考 JEP 451。

在性能方面,Per Minborg 改进了基本数据类型之间的转换(例如,long 转 int),方法是用 VarHandle 替换现有的二进制计算。由于这些转换在 Java 序列化中广泛应用,因此性能提升近 5%。其他 JDK API 和许多库也将从这些转换中受益。详细信息请参见 Per Minborg 的文章:Java 21:性能改进揭秘。

结论

考虑到 Java 21 中所包括的丰富功能,我们有理由期待 Java 22 将成为一个稳定版本。我期待 Java 22 中的某些功能将走出预览状态,特别是 外部函数与内存API(Foreign Function & Memory API),还有作用域值(Scoped Values)和 结构化并发(Structured Concurrency),后两者通过简化并发应用程序的编写来补充虚拟线程(Virtual Threads)。

要查找 Java 21 中的所有更改,请参阅发行说明。

你现在工作中使用的是哪个 Java 版本?你最期待 Java 21 版本中的哪个功能?请在评论区谈谈你的看法。

参考链接

  1. Formatter:https://download.java.net/java/early_access/jdk21/docs/api/java.base/java/util/Formatter.html

  2. JEP 430:https://openjdk.org/jeps/430

  3. JEP 431:https://openjdk.org/jeps/431

  4. JEP 439:https://openjdk.org/jeps/439

  5. JEP 440:https://openjdk.org/jeps/440

  6. JEP 441:https://openjdk.org/jeps/441

  7. JEP 442:https://openjdk.org/jeps/442

  8. JEP 443:https://openjdk.org/jeps/443

  9. JEP 444:https://openjdk.org/jeps/444

  10. JEP 445:https://openjdk.org/jeps/445

  11. JEP 446:https://openjdk.org/jeps/446

  12. JEP-448:https://openjdk.org/jeps/448

  13. JEP 449:https://openjdk.org/jeps/449

  14. JEP 451:https://openjdk.org/jeps/451

  15. JEP 452:https://openjdk.org/jeps/452

  16. JEP 453:https://openjdk.org/jeps/453

  17. Java 版本年鉴 - Java 21 中的新 API:https://javaalmanac.io/jdk/21/apidiff/20/

  18. Java 21:性能改进揭秘:https://minborgsjavapot.blogspot.com/2023/01/java-21-performance-improvements.html

  19. 发行说明:https://jdk.java.net/21/release-notes

相关推荐

MySQL进阶五之自动读写分离mysql-proxy

自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...

Postgres vs MySQL_vs2022连接mysql数据库

...

3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?

引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...

一文由浅入深带你完全掌握MySQL的锁机制原理与应用

本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...

验证Mysql中联合索引的最左匹配原则

后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...

MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)

目录1.索引基础...

你会看 MySQL 的执行计划(EXPLAIN)吗?

SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...

MySQL 从入门到精通(四)之索引结构

索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...

mysql总结——面试中最常问到的知识点

mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...

mysql总结——面试中最常问到的知识点(2)

首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...

MySQL基础全知全解!超详细无废话!轻松上手~

本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...

深入剖析 MySQL 中的锁机制原理_mysql 锁详解

在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...

Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析

引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...

MySQL基础篇:DQL数据查询操作_mysql 查

一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...

MySql:索引的基本使用_mysql索引的使用和原理

一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...