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 的预览特性中,instanceofswitch 全面支持所有原始类型,包括 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 是StructuredTaskScopeStructuredTaskScope 支持将任务拆分为多个并发子任务,在它们自己的线程中执行,并且子任务必须在主任务继续之前完成。

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); // 调用父类构造函数// ... 其他初始化代码}
}

  ——EOF——


福利:

扫码回复【酒店】可免费领取酒店管理系统源码

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】网络编程-地址管理-IP协议后序-NAT机制-以太网MAC机制

&#x1f308;个人主页&#xff1a;努力学编程’ ⛅个人推荐&#xff1a; c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构&#xff0c;刷题刻不容缓&#xff1a;点击一起刷题 &#x1f319;心灵鸡汤&#xff1a;总有人要赢&#xff0c;为什么不能是我呢 &#x1f434…

vscode关闭git的提交提示

问题描述&#xff1a; vscode中光标停留在每一行都会有出现git仓库的提交信息&#xff0c;影响代码阅读。 解决方法&#xff1a; 左下角设置齿轮&#xff1a; 输入关键词commit input 取消勾选&#xff0c;即可解决。

Apache subversion 编译流程

目录 1. 概述2. 依赖库简介2.1 Expat2.2 Apache apr2.3 Apache apr-iconv2.4 Apache apr-util2.5 Zlib2.6 OpenSSL2.7 Sqlite2.8 Apache Serf2.9 Apache subversion3. 编译3.1 Expat编译3.1.1 源码信息3.1.2 CMake-GUI3.1.3 编译步骤3.2 APR编译3.2.1 源码信息3.2.2 编译步骤3.…

2024年【中级消防设施操作员(考前冲刺)】及中级消防设施操作员(考前冲刺)模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 中级消防设施操作员&#xff08;考前冲刺&#xff09;根据新中级消防设施操作员&#xff08;考前冲刺&#xff09;考试大纲要求&#xff0c;安全生产模拟考试一点通将中级消防设施操作员&#xff08;考前冲刺&#xf…

mp4转换成mp3,八个超简单视频转换方法

怎么将mp4转换成mp3&#xff1f;在现代数字媒体的世界中&#xff0c;视频和音频的转换变得尤为重要。许多人在观看视频时&#xff0c;常常会被其中的声音吸引&#xff0c;想要单独保存下来。这时&#xff0c;将MP4格式的视频转换为MP3格式的音频就显得尤为必要。MP4是一种常用的…

长时间认知任务中的大脑补偿机制:fNIRS和眼动追踪研究

摘要 在需要高度集中和高效完成关键任务的领域&#xff0c;如何在疲劳状态下维持认知表现是一个非常重要的问题。在这种情况下&#xff0c;帮助大脑克服疲劳的补偿机制研究就显得尤为重要。本研究探讨了生理、行为和主观测量之间的相关性&#xff0c;同时考虑了疲劳对工作记忆…

yolov5/8/9/10模型在VOC数据集上的应用【代码+数据集+python环境+GUI系统】

yolov5/8/9/10模型在VOC数据集上的应用【代码数据集python环境GUI系统】 1.背景意义 VOC数据集被广泛应用于计算机视觉领域的研究和实验中&#xff0c;特别是目标检测和图像识别任务。许多知名的目标检测算法都使用VOC数据集进行训练和测试。VOC挑战赛&#xff08;VOC Challeng…

maxwell 输出消息到 kafka

文章目录 1、kafka-producer2、运行一个Docker容器&#xff0c;该容器内运行的是Zendesk的Maxwell工具&#xff0c;一个用于实时捕获MySQL数据库变更并将其发布到Kafka或其他消息系统的应用3、进入kafka容器内部4、tingshu_album 数据库中 新增数据5、tingshu_album 数据库中 更…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第四集:制作更多的敌人

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作敌人僵尸虫Zombie 1.公式化导入制作僵尸虫Zombie素材2.制作僵尸虫Zombie的Walker.cs状态机3.制作敌人僵尸虫的playmaker状态机二、制作敌人爬虫Climber…

Gradio 自定义组件

如何使用 Gradio 自定义组件&#xff0c;Gradio 前端使用 Svelte&#xff0c;后端使用的 Python。如何自定义一个组件呢&#xff1f;Gadio 提供了类似于脚手架的命令&#xff0c;可以生成需要开发组件的前后和后端代码。 创建组件 运行如下命令&#xff0c;gradio 会自动生成…

鹏鼎控股社招校招入职SHL综合能力测评:高分攻略及真题题库解析答疑

鹏鼎控股&#xff08;深圳&#xff09;股份有限公司&#xff0c;成立于1999年4月29日&#xff0c;是一家专注于印制电路板&#xff08;PCB&#xff09;的设计、研发、制造与销售的高新技术企业。公司总部位于中国广东省深圳市&#xff0c;并在全球多个地区设有生产基地和服务中…

FinGPT金融大模型

FinGPT仓库https://github.com/AI4Finance-Foundation/FinGPT 功能&#xff1a; Adviser。根据新闻判断市场情绪&#xff08;积极、消极、中性&#xff09;&#xff0c;给出投资建议。Quantitative Trading。定制属于自己的金融助手。叫它关注某几个股票、监测消息等。可以直…

计算机网络33——文件系统

1、chmod 2、chown 需要有root权限 3、link 链接 4、unlink 创建临时文件&#xff0c;用于非正常退出 5、vi vi可以打开文件夹 ../是向外一个文件夹 6、ls ls 可以加很多路径&#xff0c;路径可以是文件夹&#xff0c;也可以是文件 ---------------------------------…

5.C_数据结构_树

概述 树的逻辑结构&#xff1a; 树中任何节点都可以有0个或多个直接后继节点&#xff0c;但最多只有一个直接前驱节点。根节点没有直接前驱节点&#xff0c;叶节点没有直接后继节点。 相关名词&#xff1a; 空树&#xff1a;树中没有节点节点的度数&#xff1a;一个节点的…

【纯小白论文代码带读】医学图像分割MASDF-Net(问题产生及解决)

论文链接&#xff1a;https://www.semanticscholar.org/paper/MASDF-Net%3A-A-Multi-Attention-Codec-Network-with-and-Fu-Deng/6ab609eb93dfd12596032174ca9603712f5c050a 代码链接&#xff1a;https://github.com/Rayicer/TransFuse 初见面代码&#xff1a; Q&am…

【字符函数】strcpy函数(字符串复制函数)+strcat函数(字符串追加)+strcmp函数(字符串比较)【笔记】

1.复制函数--------------strcpy函数 函数使用 char*strcpy&#xff08;char* destination, const char* source&#xff09; strcpy函数用于拷贝字符串&#xff0c;即将一个字符串中的内容拷贝到另一个字符串中&#xff08;会覆盖原字符串内容&#xff09;。它的参数是两个指…

大数据新视界 --大数据大厂之Kubernetes与大数据:容器化部署的最佳实践

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Java键盘输入语句

编程输入语句 1.介绍:在编程中&#xff0c;需要接受用户输入的数据&#xff0c;就可以使用键盘输入语句来获取。 2.步骤&#xff1a; 1&#xff09;导入该类的所在包&#xff0c;java.util.* 2)创建该类对象&#xff08;声明变量&#xff09; 3&#xff09;调用里面的功能 3…

面试官:什么是CAS?存在什么问题?

大家好&#xff0c;我是大明哥&#xff0c;一个专注「死磕 Java」系列创作的硬核程序员。 回答 CAS&#xff0c;Compare And Swap&#xff0c;即比较并交换&#xff0c;它一种无锁编程技术的核心机制。其工作方式分为两步&#xff1a; 比较&#xff1a;它首先会比较内存中的某…

C++的初阶模板和STL

C的初阶模板和STL 回顾之前的内存管理&#xff0c;我们还要补充一个概念&#xff1a;内存池 也就是定位new会用到的场景&#xff0c;内存池只会去开辟空间。 申请内存也就是去找堆&#xff0c;一个程序中会有很多地方要去找堆&#xff0c;这样子效率会很低下&#xff0c;为了…