Java 23 的12 个新特性!!
Java 23 来啦!和 Java 22 一样,这也是一个非 LTS(长期支持)版本,Oracle 仅提供六个月的支持。下一个长期支持版是 Java 25,预计明年 9 月份发布。

Java 23 一共有 12 个新特性!
有同学表示,Java 8 还没学完呢,又要学新特性?人麻了啊。。。
别担心,其实改动并不大!
我抽时间认真看了一下新特性,并对这些新特性做了详细的解读,希望对你有帮助!
本文内容概览:

JEP 455: 模式中的原始类型、instanceof 和 switch(预览)
在 JEP 455 之前, instanceof 只支持引用类型,switch 表达式和语句的 case 标签只能使用整数字面量、枚举常量和字符串字面量。
JEP 455 的预览特性中,instanceof 和 switch 全面支持所有原始类型,包括 byte, short, char, int, long, float, double, boolean。
// 传统写法
if (i >= -128 && i <= 127) {byte b = (byte)i;... b ...
}// 使用 instanceof 改进
if (i instanceof byte b) {... b ...
}long v = ...;
// 传统写法
if (v == 1L) {// ...
} else if (v == 2L) {// ...
} else if (v == 10_000_000_000L) {// ...
}// 使用 long 类型的 case 标签
switch (v) {case 1L:// ...break;case 2L:// ...break;case 10_000_000_000L:// ...break;default:// ...
}
JEP 456: 类文件 API(第二次预览)
类文件 API 在 Java 22 进行了第一次预览,由 JEP 457 提出。
类文件 API 的目标是提供一套标准化的 API,用于解析、生成和转换 Java 类文件,取代过去对第三方库(如 ASM)在类文件处理上的依赖。
// 创建一个 ClassFile 对象,这是操作类文件的入口。
ClassFile cf = ClassFile.of();
// 解析字节数组为 ClassModel
ClassModel classModel = cf.parse(bytes);// 构建新的类文件,移除以 "debug" 开头的所有方法
byte[] newBytes = cf.build(classModel.thisClass().asSymbol(),classBuilder -> {// 遍历所有类元素for (ClassElement ce : classModel) {// 判断是否为方法 且 方法名以 "debug" 开头if (!(ce instanceof MethodModel mm&& mm.methodName().stringValue().startsWith("debug"))) {// 添加到新的类文件中classBuilder.with(ce);}}});
JEP 467:Markdown 文档注释
在 JavaDoc 文档注释中可以使用 Markdown 语法,取代原本只能使用 HTML 和 JavaDoc 标签的方式。
Markdown 更简洁易读,减少了手动编写 HTML 的繁琐,同时保留了对 HTML 元素和 JavaDoc 标签的支持。这个增强旨在让 API 文档注释的编写和阅读变得更加轻松,同时不会影响现有注释的解释。Markdown 提供了对常见文档元素(如段落、列表、链接等)的简化表达方式,提升了文档注释的可维护性和开发者体验。

Markdown 文档注释
JEP 469:向量 API(第八次孵化)
向量计算由对向量的一系列操作组成。向量 API 用来表达向量计算,该计算可以在运行时可靠地编译为支持的 CPU 架构上的最佳向量指令,从而实现优于等效标量计算的性能。
向量 API 的目标是为用户提供简洁易用且与平台无关的表达范围广泛的向量计算。
这是对数组元素的简单标量计算:
void scalarComputation(float[] a, float[] b, float[] c) {for (int i = 0; i < a.length; i++) {c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;}
}
这是使用 Vector API 进行的等效向量计算:
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;void vectorComputation(float[] a, float[] b, float[] c) {int i = 0;int upperBound = SPECIES.loopBound(a.length);for (; i < upperBound; i += SPECIES.length()) {// FloatVector va, vb, vc;var va = FloatVector.fromArray(SPECIES, a, i);var vb = FloatVector.fromArray(SPECIES, b, i);var vc = va.mul(va).add(vb.mul(vb)).neg();vc.intoArray(c, i);}for (; i < a.length; i++) {c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;}
}
JEP 473:流收集器(第二次预览)
流收集器在 Java 22 进行了第一次预览,由 JEP 461 提出。
这个改进使得 Stream API 可以支持自定义中间操作。
source.gather(a).gather(b).gather(c).collect(...)
JEP 471:弃用 sun.misc.Unsafe 中的内存访问方法
JEP 471 提议弃用 sun.misc.Unsafe 中的内存访问方法,这些方法将来的版本中会被移除。
这些不安全的方法已有安全高效的替代方案:
-
java.lang.invoke.VarHandle:JDK 9 (JEP 193) 中引入,提供了一种安全有效地操作堆内存的方法,包括对象的字段、类的静态字段以及数组元素。 -
java.lang.foreign.MemorySegment:JDK 22 (JEP 454) 中引入,提供了一种安全有效地访问堆外内存的方法,有时会与VarHandle协同工作。
这两个类是 Foreign Function & Memory API 的核心组件,分别用于管理和操作堆外内存。
Foreign Function & Memory API 在 Java 22 中正式转正,成为标准特性。
import jdk.incubator.foreign.*;
import java.lang.invoke.VarHandle;// 管理堆外整数数组的类
class OffHeapIntBuffer {// 用于访问整数元素的VarHandleprivate static final VarHandle ELEM_VH = ValueLayout.JAVA_INT.arrayElementVarHandle();// 内存管理器private final Arena arena;// 堆外内存段private final MemorySegment buffer;// 构造函数,分配指定数量的整数空间public OffHeapIntBuffer(long size) {this.arena = Arena.ofShared();this.buffer = arena.allocate(ValueLayout.JAVA_INT, size);}// 释放内存public void deallocate() {arena.close();}// 以volatile方式设置指定索引的值public void setVolatile(long index, int value) {ELEM_VH.setVolatile(buffer, 0L, index, value);}// 初始化指定范围的元素为0public void initialize(long start, long n) {buffer.asSlice(ValueLayout.JAVA_INT.byteSize() * start,ValueLayout.JAVA_INT.byteSize() * n).fill((byte) 0);}// 将指定范围的元素复制到新数组public int[] copyToNewArray(long start, int n) {return buffer.asSlice(ValueLayout.JAVA_INT.byteSize() * start,ValueLayout.JAVA_INT.byteSize() * n).toArray(ValueLayout.JAVA_INT);}
}
JEP 474:ZGC:默认的分代模式
Z 垃圾回收器 (ZGC) 的默认模式切换为分代模式,并弃用非分代模式,计划在未来版本中移除。这是因为分代 ZGC 是大多数场景下的更优选择。
JEP 476:模块导入声明 (预览)
模块导入声明允许在 Java 代码中简洁地导入整个模块的所有导出包,而无需逐个声明包的导入。这一特性简化了模块化库的重用,特别是在使用多个模块时,避免了大量的包导入声明,使得开发者可以更方便地访问第三方库和 Java 基本类。
此特性对初学者和原型开发尤为有用,因为它无需开发者将自己的代码模块化,同时保留了对传统导入方式的兼容性,提升了开发效率和代码可读性。
// 导入整个 java.base 模块,开发者可以直接访问 List、Map、Stream 等类,而无需每次手动导入相关包
import module java.base;public class Example {public static void main(String[] args) {String[] fruits = { "apple", "berry", "citrus" };Map<String, String> fruitMap = Stream.of(fruits).collect(Collectors.toMap(s -> s.toUpperCase().substring(0, 1),Function.identity()));System.out.println(fruitMap);}
}
JEP 477:未命名类和实例 main 方法 (第三次预览)
这个特性主要简化了 main 方法的的声明。对于 Java 初学者来说,这个 main 方法的声明引入了太多的 Java 语法概念,不利于初学者快速上手。
没有使用该特性之前定义一个 main 方法:
public class HelloWorld {public static void main(String[] args) {System.out.println("Hello, World!");}
}
使用该新特性之后定义一个 main 方法:
class HelloWorld {void main() {System.out.println("Hello, World!");}
}
进一步简化(未命名的类允许我们省略类名)
void main() {System.out.println("Hello, World!");
}
JEP 480:结构化并发 (第三次预览)
Java 19 引入了结构化并发,一种多线程编程方法,目的是为了通过结构化并发 API 来简化多线程编程,并不是为了取代java.util.concurrent,目前处于孵化器阶段。
结构化并发将不同线程中运行的多个任务视为单个工作单元,从而简化错误处理、提高可靠性并增强可观察性。也就是说,结构化并发保留了单线程代码的可读性、可维护性和可观察性。
结构化并发的基本 API 是StructuredTaskScope。StructuredTaskScope 支持将任务拆分为多个并发子任务,在它们自己的线程中执行,并且子任务必须在主任务继续之前完成。
StructuredTaskScope 的基本用法如下:
try (var scope = new StructuredTaskScope<Object>()) {// 使用fork方法派生线程来执行子任务Future<Integer> future1 = scope.fork(task1);Future<String> future2 = scope.fork(task2);// 等待线程完成scope.join();// 结果的处理可能包括处理或重新抛出异常... process results/exceptions ...} // close
结构化并发非常适合虚拟线程,虚拟线程是 JDK 实现的轻量级线程。许多虚拟线程共享同一个操作系统线程,从而允许非常多的虚拟线程。
JEP 481:作用域值 (第三次预览)
作用域值(Scoped Values)可以在线程内和线程间共享不可变的数据,优于线程局部变量,尤其是在使用大量虚拟线程时。
final static ScopedValue<...> V = new ScopedValue<>();// In some method
ScopedValue.where(V, <value>).run(() -> { ... V.get() ... call methods ... });// In a method called directly or indirectly from the lambda expression
... V.get() ...
作用域值允许在大型程序中的组件之间安全有效地共享数据,而无需求助于方法参数。
JEP 482:灵活的构造函数体(第二次预览)
在 JEP 482 之前,Java 要求在构造函数中,super(...) 或 this(...) 调用必须作为第一条语句出现。这意味着我们无法在调用父类构造函数之前在子类构造函数中直接初始化字段。
灵活的构造函数体解决了这一问题,它允许在构造函数体内,在调用 super(..) 或 this(..) 之前编写语句,这些语句可以初始化字段,但不能引用正在构造的实例。这样可以防止在父类构造函数中调用子类方法时,子类的字段未被正确初始化,增强了类构造的可靠性。
这一特性解决了之前 Java 语法限制了构造函数代码组织的问题,让开发者能够更自由、更自然地表达构造函数的行为,例如在构造函数中直接进行参数验证、准备和共享,而无需依赖辅助方法或构造函数,提高了代码的可读性和可维护性。
class Person {private final String name;private int age;public Person(String name, int age) {if (age < 0) {throw new IllegalArgumentException("Age cannot be negative.");}this.name = name; // 在调用父类构造函数之前初始化字段this.age = age;// ... 其他初始化代码}
}class Employee extends Person {private final int employeeId;public Employee(String name, int age, int employeeId) {this.employeeId = employeeId; // 在调用父类构造函数之前初始化字段super(name, age); // 调用父类构造函数// ... 其他初始化代码}
}相关文章:
Java 23 的12 个新特性!!
Java 23 来啦!和 Java 22 一样,这也是一个非 LTS(长期支持)版本,Oracle 仅提供六个月的支持。下一个长期支持版是 Java 25,预计明年 9 月份发布。 Java 23 一共有 12 个新特性! 有同学表示&…...
.NET 8 中 Entity Framework Core 的使用
本文代码:https://download.csdn.net/download/hefeng_aspnet/89935738 概述 Entity Framework Core (EF Core) 已成为 .NET 开发中数据访问的基石工具,为开发人员提供了强大而多功能的解决方案。随着 .NET 8 和 C# 10 中引入的改进,开发人…...
ai数字人分身123口播克隆数字人小程序源码_博纳软云
功能配置 一、用户 用户管理小黑屋用户反馈登录设置短信参数 二、作品 视频作品背景音乐库背景音乐分类 三、形象分身 上传记录视频要求参数配置 四、声音克隆 克隆记录参数配置声音要求文案示例 五、AI文案 生成记录创作模型模型分类Al配置 六、充值 充值订单积分套…...
从0开始学PHP面向对象内容之(类,对象,构造/析构函数)
上期我们讲了面向对象的一些基本信息,这期让我们详细的了解一下 一、面向对象—类 1、PHP类的定义语法: <?php class className {var $var1;var $var2 "constant string";function classfunc ($arg1, $arg2) {[..]}[..] } ?>2、解…...
openGauss数据库-头歌实验1-5 修改数据库
一、查看表结构与修改表名 (一)任务描述 本关任务:修改表名,并能顺利查询到修改后表的结构。 (二)相关知识 为了完成本关任务,你需要掌握: 1.如何查看表的结构; 2.如…...
《JVM第3课》运行时数据区
无痛快速学习入门JVM,欢迎订阅本免费专栏 运行时数据区结构图如下: 可分为 5 个区域,分别是方法区、堆区、虚拟机栈、本地方法栈、程序计数器。这里大概介绍一下各个模块的作用,会在后面的文章展开讲。 类加载子系统会把类信息…...
阅读笔记 Contemporary strategy analysis Chapter 14
来源:Robert M. Grant - Contemporary strategy analysis (2018) Chapter 14 External Growth Strategies: Mergers, Acquisitions, and Alliances 合并、收购和联盟 Ⅰ Introduction and Objectives 企业并购与联盟是公司实现快速扩张的重要战略工具。通过这些手段…...
2024网鼎杯青龙组wp:Crypto2
题目 附件内容如下 # coding: utf-8 #!/usr/bin/env python2import gmpy2 import random import binascii from hashlib import sha256 from sympy import nextprime from Crypto.Cipher import AES from Crypto.Util.Padding import pad from Crypto.Util.number import long…...
能通过Ping命令访问CentOS 9 Stream,但在使用Xshell连接
能通过Ping命令访问CentOS 9 Stream,但在使用Xshell进行SSH连接失败 1. **确认SSH服务状态**:2. **检查SSH配置**:要检查和设置PermitRootLogin选项,您需要编辑SSH配置文件/etc/ssh/sshd_config。以下是具体步骤:1. 打…...
Oracle 第19章:高级查询技术
在Oracle数据库中,高级查询技术是数据库管理员和开发人员必须掌握的重要技能。这些技术能够帮助优化查询性能,简化复杂的查询逻辑,并提高数据处理的效率。本章将重点讨论两个关键概念:子查询和连接与并集操作。 子查询 定义: 子…...
Excel:vba运行时错误“7“:内存溢出错误
我这里出现这个错误是在批注中插入图片时报错 原因:我插入的图片不都是jpg的类型的,但是其中的两张图片是webp类型的,但是我把文件后缀名修改成了jpg,以为变成了jpg类型的图片,但是图片在批注里面无法显示,所以运行到第…...
【MyBatis源码】BoundSql分析
基础 BoundSql是对SQL语句及参数信息的封装,它是SqlSource解析后的结果。Executor组件并不是直接通过StaticSqlSource对象完成数据库操作的,而是与BoundSql交互。BoundSql是对Executor组件执行SQL信息的封装,具体实现代码如下: …...
KTHREAD--InitialStack和KernelStack和TSS的esp0
InitialStack和TSS.esp0的关系,在这里可以看到 mov ecx, [esi_KTHREAD.InitialStack] ; esi: newthread lea eax, [ecx-210h] ; 越过FPXSAVE指令存储地址 test byte ptr [eax-1Ah], 2 ; 判断efalgs寄存器的VIF位是否为1 jnz short loc_458743 sub eax, 10h…...
Skia基础运用(Ubuntu环境下使用BUILD.gn)
1.拉取代码 git clone https://skia.googlesource.com/skia python tools/git-sync-deps // 这一步可能会出现部分错误,再次执行直到成功 // 这里面拉取完三方库之后会拉取node,linux等压缩包,从google下载上面执行完,代码就完全…...
Vue中props和data的优先级哪个更高?
前言 Vue组件之间的数据传递是一个非常重要的环节。而在组件内部,我们经常会用到props和data来管理和传递数据。那么,问题来了:当props和data有冲突时,哪个优先级更高呢? 为了更好地理解这个问题,我们先来…...
springboot2.x使用SSE方式代理或者转发其他流式接口
文章目录 1.需求描述2.代码2.1.示例controller2.2.示例service2.3.示例impl 3.测试 1.需求描述 使用SSE的方式主要还是要跟前端建立一个EventSource的链接,有了这个连接,然后往通道里写入数据流,前端自然会拿到流式数据,写啥拿啥…...
consul入门教程
一、介绍Consul Consul是由HashiCorp开发的一种服务发现和配置管理工具,它可以提供分布式系统所需的多个关键功能,如服务发现、配置管理、键值存储等。Consul可以帮助开发人员轻松构建分布式系统,提高系统的可靠性和可扩展性。 二、Consul实…...
软考:大数据架构设计
大数据总结 大数据处理系统的特征 1、鲁棒性和容错性 2、低延迟读取和更新能力 3、横向扩容 4、通用性 5、延展性 6、即席查询能力 7、最少维护能力 8、可调试性 Lambda架构 批处理层 存储数据集和生成Batch View 管理主数据集,原始的,不可变的&…...
token无感刷新+处理并发的后端方案
问题描述: 当用户通过登陆后进入一个web网站,会把token保存到localStorage。假设token过期时间30min。 那么当用户在网站快乐地玩耍了30min后,这时进行了一次提交表单,它会被重定向到登陆页面。 作为用户:我表单填了…...
【系统设计】让 Java “动起来”:动态语言与静态语言的比较及 DSL 实现
在编程语言的世界里,语言的特性决定了它们在不同场景下的适用性。动态语言和静态语言是两种常见的编程范式,它们的差异不仅影响开发者的使用习惯,还决定了它们在某些应用场景中的表现。在这篇博文中,我们将通过Python和Java这两种…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...
ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...
Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...
