从JDK 17 到 JDK 21:Java 新特性
JDK17
密封类
概念:密封类允许开发者控制哪些类可以继承或实现特定的类或接口。通过这种方式,密封类为类的继承提供了更高的安全性和可维护性。
定义:使用sealed代表该类为密封类,并用permits限制哪些类可以继承。
public sealed class Shape permits Circle, Square {// 类体
}public final class Circle extends Shape {// 类体
}public final class Square extends Shape {// 类体
}
继承类必须由final,sealed,non-sealed修饰。
- final代表该继承类不能被任何类继承
- sealed代表该类依然是继承类
- non-sealed代表该类不受任何限制
优势:
- 增强可维护性: 开发者可以清晰地定义哪些类可以扩展特定类,从而更好地控制代码的变化。
- 提高安全性: 限制类的继承可以防止不受控制的扩展,降低代码出错的概率。
- 更好的设计: 密封类可以使类的层次结构更加明确,符合设计模式的要求。
简化instanceof
在JDK16及以前需要先进行类型判断然后强制转换获取对象
public class Main {public static void main(String[] args) {Object obj = "Hello, World!"; // String 类型的对象if (obj instanceof String) {String str = (String) obj; // 强制转换System.out.println(str.toUpperCase()); // 使用转换后的字符串}}
}
在JDK17开始可以合二为一
public class Main {public static void main(String[] args) {Object obj = "Hello, World!"; // String 类型的对象if (obj instanceof String str) { // 类型检查和转换System.out.println(str.toUpperCase()); // 直接使用 str}}
}
优点:
- 简洁性: 通过将类型检查和转换合并为一个操作,代码更加简洁,减少了冗余。
- 可读性: 减少了强制转换的显式写法,使得代码更易于理解。
- 减少出错: 避免了在进行强制转换时可能出现的
ClassCastException
异常,因为编译器会确保类型检查的正确性。
增强Switch
基本示例
增强的 switch
表达式允许使用“箭头”语法 (->
),这使得每个 case
分支可以直接返回一个值或执行一段代码。以下是基本的语法示例:
int day = 3; // 假设 1 = 星期一,2 = 星期二,...String dayType = switch (day) {case 1, 7 -> "Weekend"; // 支持多个 case 用逗号分隔case 2, 3, 4, 5, 6 -> "Weekday"; // 其他工作日default -> throw new IllegalArgumentException("Invalid day: " + day); // 默认情况
};System.out.println(dayType); // 输出: Weekday
代码块支持
除了简单的返回值,switch
表达式还支持代码块,你可以在 case
中包含多行代码。这时需要使用 {}
来包裹代码块,并且要使用 yield
语句返回值。
public class Main {public static void main(String[] args) {int day = 5; // 假设 1 = 星期一,2 = 星期二,...String dayType = switch (day) {case 1, 7 -> "Weekend";case 2, 3, 4, 5, 6 -> "Weekday";default -> throw new IllegalArgumentException("Invalid day: " + day);};System.out.println("Day " + day + " is a " + dayType);}
}
文本块增强
基本概念
文本块允许以更直观的方式定义多行字符串,使用三重引号("""
)来包裹文本内容。这样,文本块中的换行、缩进和其他空白字符将被直接保留,增强了可读性。
基本用法
基本的文本块用法如下所示:
java复制代码String textBlock = """This is a text block.It can span multiple lines.""";
文本块的增强
在 Java 17 中,对文本块进行了增强,主要体现在以下几个方面:
换行和缩进处理
- 自动去除公共前缀: 文本块的自动缩进特性可以去除公共前缀。这意味着,如果文本块的所有行都有相同的前缀空白(缩进),在生成的字符串中,这些空白将会被自动去除。
示例:
java复制代码String textBlock = """Line 1Line 2Line 3""";System.out.println(textBlock);
输出将是:
Line 1
Line 2
Line 3
在这个示例中,公共前缀的空白会被自动去除。
使用表达式插入文本
文本块可以与表达式结合,允许在文本块中插入动态内容。这使得文本块更加灵活和动态。
示例:
java复制代码String name = "John";
String greeting = """Hello, %s!Welcome to the Java world.""".formatted(name);System.out.println(greeting);
输出将是:
Hello, John!
Welcome to the Java world.
在这个示例中,使用了 String.formatted()
方法来插入变量。
支持 Unicode 字符
文本块支持 Unicode 字符,使得在字符串中包含特殊字符变得更加方便。例如,你可以直接在文本块中使用中文字符、表情符号等。
示例:
String unicodeTextBlock = """Hello, 世界! 🌍This is a text block with Unicode characters.""";System.out.println(unicodeTextBlock);
输出将是:
Hello, 世界! 🌍
This is a text block with Unicode characters.
JDK21
虚拟线程
为什么引入?
线程的缺点有两个:
- 创建销毁成本高
- 频繁切换成本高
第一个缺点已经通过线程池解决了,第二个在JDK21通过虚拟线程也得到了解决。
概念与优势
虚拟线程被设计为轻量级的执行单元,可以在 JVM 中并发执行。虚拟线程使得开发者能够创建和管理数以千计的并发任务,而无需像使用传统线程那样消耗大量资源。
优势:
- 轻量级: 虚拟线程的内存开销和启动时间都大大低于操作系统线程。这使得创建和管理虚拟线程变得更加高效。
- 易于使用: 开发者可以使用简单的代码结构来编写并发任务,而无需管理线程的生命周期和状态。
- 高并发: 虚拟线程允许在单个 JVM 实例中并发运行数以千计的虚拟线程,非常适合 I/O 密集型和网络应用程序。
使用
虚拟线程在代码上兼容极好,跟传统线程区别不大。
直接创建虚拟线程
public class VirtualThreadExample {public static void main(String[] args) {Thread virtualThread = Thread.ofVirtual().start(() -> {System.out.println("This is a virtual thread!");});virtualThread.join();}
}
通过线程池获取
// 创建一个虚拟线程池ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();// 提交多个任务到虚拟线程池for (int i = 0; i < 10; i++) {final int taskId = i;executor.submit(() -> {});}// 关闭线程池executor.shutdown();
序列集合
在之前的版本中,List、Set、LinkedHashSet这些不同的集合获取首尾元素的方式不同,api不同,很折磨人。
序列集合是一类新接口,与常规集合(如 List
和 Set
)不同,序列集合强调保持元素的插入顺序,并提供了一种更灵活的元素处理方式。
interface sequencedcollection<E>extends colection<E>{Sequencedco1lection<E> reversed(),void addLast(E);E getFirst();E getLast();E removeFirst;E removeLast();
}
有个序列集合后就不用因为不统一的api发愁了。
Record
介绍
定义: Record
是一种特殊的类,用于表示不可变的数据模型。它自动为每个字段生成构造函数、访问器(getter)和其他一些方法(如 toString()
、equals()
和 hashCode()
)。
语法: 创建 Record
类的语法非常简洁,类似于定义普通类。记录类的定义如下:
public record Person(String name, int age) { }
特性
不可变性:
Record
实例是不可变的,一旦创建,字段的值就不能被修改。这确保了数据的一致性和安全性,尤其是在多线程环境中。
自动生成方法:
- 构造函数: 自动生成一个构造函数,接受所有字段作为参数。
- 访问器: 为每个字段生成一个访问器方法,名称与字段相同,但没有前缀。例如,上述
Person
记录将具有name()
和age()
方法。 toString()
: 自动生成一个toString()
方法,返回所有字段的名称和值。equals()
和hashCode()
: 自动实现equals()
和hashCode()
方法,以支持基于内容的比较和集合操作。
JDK21增强特性
record
中的泛型
Record
现在可以定义为泛型类。这使得你能够创建更具通用性和复用性的记录类:
public record Box<T>(T content) { }
sealed
Record
可以将 Record
声明为 sealed
,限制哪些类可以扩展该 Record
:
public sealed record Shape permits Circle, Square { }public record Circle(double radius) extends Shape { }public record Square(double side) extends Shape { }
记录的嵌套记录
你可以在 Record
中嵌套另一个 Record
,这使得组织复杂数据模型更为简洁:
public record Address(String street, String city) { }public record Person(String name, int age, Address address) { }
使用场景
数据传输对象(DTO)
场景描述: DTO 是一种简单的对象,用于封装数据并在不同层或模块之间传递。使用 Record
可以减少样板代码。
示例代码:
// 数据传输对象
public record UserDTO(String username, String email, int age) { }public class UserService {public UserDTO getUser(int id) {// 假设从数据库获取用户数据return new UserDTO("xxx", "xxx@qq.com", 25);}
}public class Main {public static void main(String[] args) {UserService userService = new UserService();UserDTO user = userService.getUser(1);System.out.println(user.username()); System.out.println(user.email()); System.out.println(user.age()); }
}
返回类型
场景描述: 方法需要返回多个值时,使用 Record
可以将这些值组合在一起,避免使用数组或其他复杂的数据结构。
配置和设置
场景描述: 在需要表示一组配置参数或设置选项时,Record
可以提供清晰和易于维护的表示方式。
示例代码:
// 配置类
public record DatabaseConfig(String url, String username, String password) { }
总结
通过记录我们可以把之前需要创建类或者构建复杂数据结构的场景简化,记录会自动创建一些方法供我们使用,所以只需要简单声明记录类即可。
相关文章:
从JDK 17 到 JDK 21:Java 新特性
JDK17 密封类 概念:密封类允许开发者控制哪些类可以继承或实现特定的类或接口。通过这种方式,密封类为类的继承提供了更高的安全性和可维护性。 定义:使用sealed代表该类为密封类,并用permits限制哪些类可以继承。 public sea…...

【计算机网络 - 基础问题】每日 3 题(五十七)
✍个人博客:https://blog.csdn.net/Newin2020?typeblog 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞…...

第十二章 章节练习created的应用
目录 一、引言 二、运行效果图 三、完整代码 一、引言 构建一个新闻的页面,页面在响应式数据准备好之后(即created),就向后台接口请求获取新闻数据列表,然后赋值给Vue实例中的list列表,这个请求逻辑我…...
Unity 游戏性能优化实践:内存管理与帧率提升技巧
1. 引言 随着移动设备性能的逐步提升,游戏玩家对画质和流畅度的要求越来越高。优化 Unity 游戏性能不仅可以提升用户体验,还能降低设备的功耗,延长电池寿命。这篇文章将深入探讨如何在 Unity 中优化游戏的内存管理与帧率,通过多方…...
C++游戏开发详解
C 是一种广泛使用的编程语言,尤其在游戏开发领域有着不可替代的地位。它提供了对底层硬件的直接访问能力,允许开发者优化性能,这对于追求高帧率和低延迟的游戏来说至关重要。本文将详细介绍使用 C 进行游戏开发的基础知识和技术要点ÿ…...
三、大模型(LLMs)微调面
本文精心汇总了多家顶尖互联网公司在大模型基础知识考核中的核心考点,并针对这些考点提供了详尽的解答。并提供电子版本,见于文末百度云盘链接中,供读者查阅。 一、大模型微调 • 1 如果想要在某个模型基础上做全参数微调,究竟需要…...

Flutter升级与降级
升级 版本升级 // 升级到指定版本flutter upgrade 版本号// 升级到最新版本flutter upgrade 降级 1.需要先确定想要降级的版本号。 2.切换到系统安装Flutter的目录 3.在https://github.com/flutter/flutter,找到要回退的版本号对应的commit序号(具…...
分布式并发场景的核心问题与解决方案
文章目录 分布式并发场景的核心问题与解决方案一、核心问题分析1. 分布式事务问题2. 数据一致性问题3. 并发控制问题4. 分布式锁失效问题 二、解决方案1. 分布式事务解决方案1.1 可靠消息最终一致性方案1.2 TCC方案实现 2. 缓存一致性解决方案2.1 延迟双删策略2.2 Canal方案 3.…...
D - Many Segments 2(ABC377)
题意:给定n和m,给定n个区间li,ri,求出满足区间lr不完全包含区间liri的个数 分析:用优先队列对区间r进行排序,i表示左区间,每次找到右区间加入即可。 代码: #include<bits/stdc…...

数组指针和指针数组的区别
数组指针和指针数组的区别 根据我个人的理解如下: 数组指针:指向数组的指针。着重点在于最后的指针两个字。 指针数组: 所有元素都是指针的数组。着重点在于最后的数组两个字。 另外来看助手的回答: Kimi: 1. **数组指针(Ar…...
【VUE点击父组件按钮,跳转到子组件】
要实现在Vue中,父组件通过点击按钮进入子组件的 <el-dialog> 弹窗,并在弹窗中嵌套 <el-table> 表格,可以按照以下步骤进行编写代码: 在父组件中,定义一个数据属性用于控制子组件弹窗的显示与隐藏。 data…...
Java列表排序:方法与实践
在Java编程中,列表排序是一个常见且重要的任务。本文将介绍Java中对列表进行排序的几种方法,包括使用Collections.sort()、List.sort()以及自定义排序规则。 1. 使用Collections.sort() Collections.sort()是Java提供的一个静态方法,用于对…...

哈希及其封装实现unordermap和set
哈希 直接定址法 哈希和之前的红黑树的区别就是,它是通过映射关系来找到目标的,可以把它想象成之前排序的计数排序,那其实就是哈希的一种方法,叫做直接定址法。 对于比较集中的数据,它只需要开一段区间,…...

在 AMD GPU 上构建解码器 Transformer 模型
Building a decoder transformer model on AMD GPU(s) — ROCm Blogs 2024年3月12日 作者 Phillip Dang. 在这篇博客中,我们展示了如何使用 PyTorch 2.0 和 ROCm 在单个节点上的单个和多个 AMD GPU 上运行Andrej Karpathy’s beautiful PyTorch re-implementation …...

Canvas简历编辑器-选中绘制与拖拽多选交互设计
Canvas简历编辑器-选中绘制与拖拽多选交互设计 在之前我们聊了聊如何基于Canvas与基本事件组合实现了轻量级DOM,并且在此基础上实现了如何进行管理事件以及多层级渲染的能力设计。那么此时我们就依然在轻量级DOM的基础上,关注于实现选中绘制与拖拽多选交…...
简单工厂(Simple Factory)
简单工厂(Simple Factory) 在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。 说明: 简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,让简单工厂类来决定应该用哪…...
ffmpeg拉流分段存储到文件-笔记
通过ffmpeg可以从rtsp网络流拉取数据并存储到本地文件里,如下命令。做个笔记 ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.168:6880/live -c copy -f segment -segment_time 60 stream_piece_%d.mp4这条 ffmpeg 命令的作用是从一个 RTSP 流中捕获视频ÿ…...
Java 实习工资大概是多少?——解读影响薪资的因素
文章目录 1. 城市因素:一线、二线的差距2. 公司类型:互联网公司、外企和传统企业的差别3. 个人能力:经验、技术栈的重要性4. 其他影响因素:学历和实习时间总结推荐阅读文章 Java 开发作为广泛应用的职业方向,实习工资的…...

【Linux】万字详解:Linux文件系统与软硬链接
🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 🚀 前言 一: 🔥 磁盘的物理结构二: 🔥 磁盘的存储结构 三: 🔥 磁盘的逻辑结构 四: &#…...
spacenavd
介绍spacenavd开源项目,主要是因为在斯坦福大学的UMI项目中使用了该项目。在斯坦福大学的 UMI(Universal Manipulation Interface)项目中,Spacenavd 主要用于处理 3D Space Mouse(空间鼠标)的输入…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...