Java SE 24 新增特性

news/2025/3/19 17:26:24/文章来源:https://www.cnblogs.com/greyzeng/p/18781401

Java SE 24 新增特性

作者:Grey

原文地址:

博客园:Java SE 24 新增特性

CSDN:Java SE 24 新增特性

源码

源仓库: Github:java_new_features

Patterns、instanceof 和 switch 可以匹配更多类型(第二次预览)

通过允许在所有模式上下文中使用原始类型来增强模式匹配,Java 16 中引入了与 instanceof 的模式匹配,在 Java 21 中引入了与 switch 的模式匹配。

public class PrimitiveTypesTest {void main() {test1("hello world");test2("hello world");test1(56);test2(56);test1(java.time.LocalDate.now());test2(java.time.LocalDate.now());}private static void test1(Object obj) {if (obj instanceof String s && s.length() >= 5) {System.out.println(s.toUpperCase());} else if (obj instanceof Integer i) {System.out.println(i * i);} else {System.out.println(obj);}}private static void test2(Object obj) {switch (obj) {case String s when s.length() >= 5 -> System.out.println(s.toUpperCase());case Integer i -> System.out.println(i * i);case null, default -> System.out.println(obj);}}
}

JEP 455 在 Java 23 中引入了两项变更:

  • 可以在 switch 表达式和语句中使用所有基元类型,包括 long、float、double 和 boolean。

  • 其次,我们还可以在模式匹配中使用所有基元类型,包括 instanceof 和 switch。

在这两种情况下,即通过 long、float、double 和布尔类型进行 switch 以及使用基元变量进行模式匹配时,与所有新的 switch 功能一样,switch 必须要涵盖所有可能的情况。

private static void test3(int x) {switch (x) {case 1, 2, 3 -> System.out.println("Low");case 4, 5, 6 -> System.out.println("Medium");case 7, 8, 9 -> System.out.println("High");}
}

模块导入声明(第二次预览)

这个功能在JDK 23 上是第一次预览,主要功能是通过简洁地导入模块导出的所有包的功能来增简化了模块库的重复使用,但不要求导入代码本身必须在模块中。

自 Java 1.0 起,java.lang 包中的所有类都会自动导入到每个 .java 文件中。这就是为什么我们无需导入语句就能使用 ObjectStringIntegerExceptionThread 等类的原因。

我们还可以导入完整的包。例如,导入 java.util.* 意味着我们不必单独导入 ListSetMapArrayListHashSetHashMap 等类。

JEP 467现在允许我们导入完整的模块,更准确地说,是导入模块导出的包中的所有类。

例如,我们可以按如下方式导入完整的 java.base 模块,然后使用该模块中的类(例如 ListMapCollectorsStream),而无需进一步导入:

package git.snippets.jdk23;import module java.base;public class ModuleImportDeclarationsTest {void main() {System.out.println(groupByFirstLetter("a", "abc", "bcd", "ddd", "dddc", "dfc", "bc"));}public static Map<Character, List<String>> groupByFirstLetter(String... values) {return Stream.of(values).collect(Collectors.groupingBy(s -> Character.toUpperCase(s.charAt(0))));}
}

如果有两个同名的导入类,例如下面示例中的 Date,编译器就会出错:

import module java.base;
import module java.sql;

如果一个导入模块临时导入了另一个模块,那么我们也可以使用临时导入模块导出包中的所有类,而无需显式导入。

例如,java.sql 模块转义导入了 java.xml 模块:

module java.sql {. . .requires transitive java.xml;. . .
}

因此,在下面的示例中,我们不需要显式导入 SAXParserFactory 和 SAXParser,也不需要显式导入 java.xml 模块:

SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();

灵活的构造函数主体(第三次预览)

这个功能在 JDK 23 上是第二次预览,现在是第三次预览,下述代码中,Child1的构造函数,只能先通过super构造父类,然后才能初始化子类的 b 这个变量。

public class FlexibleConstructorBodies {void main() {new Child1(1, 2);}
}class Parent {private final int a;public Parent(int a) {this.a = a;printMe();}void printMe() {System.out.println("a = " + a);}
}// JDK 23 之前
class Child1 extends Parent {private final int b;public Child1(int a, int b) {super(verifyParamsAndReturnA(a, b));this.b = b;}@Overridevoid printMe() {super.printMe();System.out.println("b = " + b);}private static int verifyParamsAndReturnA(int a, int b) {if (a < 0 || b < 0) throw new IllegalArgumentException();return a;}
}

当我们执行

new Child1(1,2);

这段代码的时候,本来我们期待返回的是

a = 1
b = 2

但是由于父类在构造时候调用了printMe(),且这个调用是在 b 变量初始化之前调用的,所以导致程序执行的结果是

a = 1
b = 0

今后,在使用 super(...) 调用父类构造函数之前,以及在使用 this(...) 调用本类的构造函数之前,我们可以执行任何不访问当前构造实例(即不访问其字段)的代码,

此外,我们还可以初始化正在构造的实例的字段。详见JEP 482

在 JDK 24 上,上述代码可以调整为:

class Child2 extends Parent {private final int b;public Child2(int a, int b) {if (a < 0 || b < 0) throw new IllegalArgumentException(); this.b = b;                                                super(a);}@Overridevoid printMe() {super.printMe();System.out.println("b = " + b);}
}

其中构造函数中,a和b的初始化和判断,都可以在super(...)函数调用之前,
执行

new Child2(1,2);

打印结果为预期结果

a = 1
b = 2

main方法的精简写法(第四次预览)

最早出现在 JDK 21 中,见Java SE 21 新增特性

原来我们写一个main方法,需要

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

而且Java文件的名称需要和UnnamedClassesAndInstanceMainMethodsTest保持一致,到了JDK 24,上述代码可以简化成

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

甚至连 public class ... 这段也不需要写,在JDK 24版本中,这个功能是第四次预览。

结构化并发(第四次预览)

JEP 499 引入了结构化并发(Structured Concurrency),它确保相关的任务一起启动、一起管理,使并发编程更安全、更易于理解

让我们通过一个简单的示例来理解它:并行获取用户数据和订单数据,并比较传统方式结构化并发的实现方式。

传统方式(没有结构化并发)

在传统方法中,我们使用 ExecutorService 并手动管理任务执行和取消:

import java.util.concurrent.*;public class TraditionalConcurrencyExample {private static final ExecutorService executor = Executors.newFixedThreadPool(2);public static void main(String[] args) throws ExecutionException, InterruptedException {Future<String> userFuture = executor.submit(() -> fetchUserData());Future<String> orderFuture = executor.submit(() -> fetchOrderData());try {String userData = userFuture.get(); // 阻塞直到用户数据返回String orderData = orderFuture.get(); // 阻塞直到订单数据返回System.out.println("用户: " + userData + ", 订单: " + orderData);} finally {executor.shutdown();}}static String fetchUserData() {try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }return "用户数据";}static String fetchOrderData() {try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }return "订单数据";}
}

存在的问题:
子任务管理复杂——没有清晰的父子关系,难以控制任务的生命周期。

手动异常处理——需要自行管理任务失败时的行为。

资源泄漏风险——如果一个任务失败,另一个任务可能仍在运行,可能导致不一致的状态。

使用结构化并发

现在,我们使用 StructuredTaskScope 让任务在相同的作用域中执行,并确保它们要么一起完成,要么一起失败

import java.util.concurrent.*;
import jdk.incubator.concurrent.StructuredTaskScope;public class StructuredConcurrencyExample {public static void main(String[] args) throws InterruptedException, ExecutionException {try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {StructuredTaskScope.Subtask<String> userTask = scope.fork(() -> fetchUserData());StructuredTaskScope.Subtask<String> orderTask = scope.fork(() -> fetchOrderData());scope.join();  // 等待所有任务完成scope.throwIfFailed();  // 如果有任务失败,取消所有任务并抛出异常String userData = userTask.get();String orderData = orderTask.get();System.out.println("用户: " + userData + ", 订单: " + orderData);}}static String fetchUserData() {try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }return "用户数据";}static String fetchOrderData() {try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }return "订单数据";}
}

结构化并发的优势如下:

任务管理更清晰——所有任务都在 StructuredTaskScope 作用域内,代码更加易读
自动清理——如果任何一个任务失败,所有任务都会被取消,不会出现部分完成的情况。
更好的错误处理——异常可以在 scope.throwIfFailed() 统一管理,避免手动 try-catch。
更容易调试——所有任务都有明确的父作用域,方便排查问题。

结构化并发(Structured Concurrency)让并行任务的执行更安全、更易维护。它确保任务要么一起成功完成,要么一起失败取消,避免了传统并发编程中的各种问题,如任务泄漏、异常传播困难等。

更多

Java SE 7及以后各版本新增特性,持续更新中...

参考资料

Java Language Changes for Java SE 24

JDK 24 Release Notes

JAVA 24 FEATURES(WITH EXAMPLES

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/901607.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工具-安装uTools搜索工具

安装uTools工具 通过网盘分享的文件:uTools 链接: https://pan.baidu.com/s/10QoYus5aWO3b5bvTZ-c9uw?pwd=sky1 提取码: sky1 使用效果:alt + 空格键

“四预”驱动数字孪生水利:让智慧治水守护山河安澜

近年来,从黄河秋汛到海河特大洪水,从珠江流域性洪灾到长江罕见骤旱,极端天气频发让水安全问题备受关注。如何实现“治水于未发”?数字孪生水利以“预报、预警、预演、预案”(四预)为核心,正在掀起一场水利治理的智慧革命。 一、数字孪生水利:从物理世界到虚拟镜像的跃迁…

Pydantic模型继承解析:从字段继承到多态模型

title: Pydantic模型继承解析:从字段继承到多态模型 date: 2025/3/19 updated: 2025/3/19 author: cmdragon excerpt: 涵盖字段继承、属性覆盖、多态模型等关键机制。将掌握类型安全的继承体系构建方法,实现企业级数据校验方案,避免传统面向对象继承的常见陷阱。 categori…

20242428 实验一《Python程序设计》实验报告

学号20242428《Python程序设计》实验一报告 课程:《Python程序设计》 班级: 2424 姓名: 虎岳 学号:20242428 实验教师:王志强 实验日期:2025年3月19日 必修/选修: 公选课 1.实验内容 1.熟悉Python开发环境; 2.练习Python运行、调试技能;(编写书中的程序,并进行调试…

记录一次PG数据库连接数超最大值问题

报错内容: nested exception is org.postgresql.util.PSQLException: FATAL: remaining connection slots are reserved for non-replication superuser connections排查手段 : SELECT COUNT(*) FROM pg_stat_activity; 查询活跃的连接 SHOW max_connections; 查询数…

StarRocks 升级注意事项

前段时间升级了生产环境的 StarRocks,从 3.3.3 升级到了 3.3.9,期间还是踩了不少坑所以在这里记录下。因为我们的集群使用的是存算分离的版本,也是使用官方提供的 operator 部署在 kubernetes 里的,所以没法按照官方的流程进入虚拟机手动启停对应的服务。 只能使用 operato…

Grafana 添加官方模板

Refer 官方的模板地址: https://grafana.com/grafana/dashboards/ 1.进入到dashboard页面 2.点击New->Import 3.输入想要导入模板的id或者url地址都行 比如你想导入模板url地址是:https://grafana.com/grafana/dashboards/14584-argocd/ 你就可以填写上面的url地址,也可…

05C++数据类型——教学(2)

四、 数据类型.转换 教学视频 1. 数据类型类型名 类型声明 解释说明整型 int -2147483648 到 2147483647 的范围的整数长整形 long long 比上面大很多很多,这里装不下,具体搜索字符型 char 赋值只能是一个字符,比如 A,必须用单引号,双表示字符串不是字符浮点型 float 也叫…

革新科技!通过EtherCAT与Profinet网关实现温湿度监控,医药设备领域的智能革命来临!

通过网关EtherCAT---Profinet 通讯实现温湿度监控项目背景 某医药企业制药设备采用 EtherCAT 作为主控制总线,负责高速设备控制。温湿度传感器、执行器等环境监控设备基于 Profinet 通讯。 为实现机器整体环境参数的实时采集与集中监控,需要在 EtherCAT 总线与 Profinet 网络…

grafana添加跳转的超链接

1.进入到你想设置链接的dashboard中 2.选中表格-》点击Edit->进入到table 3.找到右侧栏中的 Data links -》add link:输入title和url地址,点击save 4.点击右上角的“Save dashboard”按钮保存 此时,表格中的数据点击时,就可以跳转了。

数独游戏 | 数字益智游戏①

依托国产的 AI 豆包完成的网页端的数独益智游戏。前情概要 2025年03月19日,依托豆包设计了数独游戏,嵌入到我的博客,数字益智游戏,欢迎体验。 数独游戏数独游戏.sudoku-game-container { font-family: Arial, sans-serif; display: flex; flex-direction: column; align-it…

itext5生成多个PDF并合并

PDF批量生成并合并为1个PDF 单个生成/*** 根据id查询数据* @param id 数据id* @return*/private Map<String, String> queryEntityDataById(String id) {//根据id查询Box entity = BoxService.getById(id);Map<String, String> data = new HashMap<String, Stri…