当前位置: 首页 > news >正文

从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不同,很折磨人。

序列集合是一类新接口,与常规集合(如 ListSet)不同,序列集合强调保持元素的插入顺序,并提供了一种更灵活的元素处理方式。

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 密封类 概念&#xff1a;密封类允许开发者控制哪些类可以继承或实现特定的类或接口。通过这种方式&#xff0c;密封类为类的继承提供了更高的安全性和可维护性。 定义&#xff1a;使用sealed代表该类为密封类&#xff0c;并用permits限制哪些类可以继承。 public sea…...

【计算机网络 - 基础问题】每日 3 题(五十七)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…...

第十二章 章节练习created的应用

目录 一、引言 二、运行效果图 ​三、完整代码 一、引言 构建一个新闻的页面&#xff0c;页面在响应式数据准备好之后&#xff08;即created&#xff09;&#xff0c;就向后台接口请求获取新闻数据列表&#xff0c;然后赋值给Vue实例中的list列表&#xff0c;这个请求逻辑我…...

Unity 游戏性能优化实践:内存管理与帧率提升技巧

1. 引言 随着移动设备性能的逐步提升&#xff0c;游戏玩家对画质和流畅度的要求越来越高。优化 Unity 游戏性能不仅可以提升用户体验&#xff0c;还能降低设备的功耗&#xff0c;延长电池寿命。这篇文章将深入探讨如何在 Unity 中优化游戏的内存管理与帧率&#xff0c;通过多方…...

C++游戏开发详解

C 是一种广泛使用的编程语言&#xff0c;尤其在游戏开发领域有着不可替代的地位。它提供了对底层硬件的直接访问能力&#xff0c;允许开发者优化性能&#xff0c;这对于追求高帧率和低延迟的游戏来说至关重要。本文将详细介绍使用 C 进行游戏开发的基础知识和技术要点&#xff…...

三、大模型(LLMs)微调面

本文精心汇总了多家顶尖互联网公司在大模型基础知识考核中的核心考点&#xff0c;并针对这些考点提供了详尽的解答。并提供电子版本&#xff0c;见于文末百度云盘链接中&#xff0c;供读者查阅。 一、大模型微调 • 1 如果想要在某个模型基础上做全参数微调&#xff0c;究竟需要…...

Flutter升级与降级

升级 版本升级 // 升级到指定版本flutter upgrade 版本号// 升级到最新版本flutter upgrade 降级 1.需要先确定想要降级的版本号。 2.切换到系统安装Flutter的目录 3.在https://github.com/flutter/flutter&#xff0c;找到要回退的版本号对应的commit序号&#xff08;具…...

分布式并发场景的核心问题与解决方案

文章目录 分布式并发场景的核心问题与解决方案一、核心问题分析1. 分布式事务问题2. 数据一致性问题3. 并发控制问题4. 分布式锁失效问题 二、解决方案1. 分布式事务解决方案1.1 可靠消息最终一致性方案1.2 TCC方案实现 2. 缓存一致性解决方案2.1 延迟双删策略2.2 Canal方案 3.…...

D - Many Segments 2(ABC377)

题意&#xff1a;给定n和m&#xff0c;给定n个区间li&#xff0c;ri&#xff0c;求出满足区间lr不完全包含区间liri的个数 分析&#xff1a;用优先队列对区间r进行排序&#xff0c;i表示左区间&#xff0c;每次找到右区间加入即可。 代码&#xff1a; #include<bits/stdc…...

数组指针和指针数组的区别

数组指针和指针数组的区别 根据我个人的理解如下&#xff1a; 数组指针&#xff1a;指向数组的指针。着重点在于最后的指针两个字。 指针数组&#xff1a; 所有元素都是指针的数组。着重点在于最后的数组两个字。 另外来看助手的回答: Kimi: 1. **数组指针&#xff08;Ar…...

【VUE点击父组件按钮,跳转到子组件】

要实现在Vue中&#xff0c;父组件通过点击按钮进入子组件的 <el-dialog> 弹窗&#xff0c;并在弹窗中嵌套 <el-table> 表格&#xff0c;可以按照以下步骤进行编写代码&#xff1a; 在父组件中&#xff0c;定义一个数据属性用于控制子组件弹窗的显示与隐藏。 data…...

Java列表排序:方法与实践

在Java编程中&#xff0c;列表排序是一个常见且重要的任务。本文将介绍Java中对列表进行排序的几种方法&#xff0c;包括使用Collections.sort()、List.sort()以及自定义排序规则。 1. 使用Collections.sort() Collections.sort()是Java提供的一个静态方法&#xff0c;用于对…...

哈希及其封装实现unordermap和set

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

在 AMD GPU 上构建解码器 Transformer 模型

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

Canvas简历编辑器-选中绘制与拖拽多选交互设计

Canvas简历编辑器-选中绘制与拖拽多选交互设计 在之前我们聊了聊如何基于Canvas与基本事件组合实现了轻量级DOM&#xff0c;并且在此基础上实现了如何进行管理事件以及多层级渲染的能力设计。那么此时我们就依然在轻量级DOM的基础上&#xff0c;关注于实现选中绘制与拖拽多选交…...

简单工厂(Simple Factory)

简单工厂&#xff08;Simple Factory&#xff09; 在创建一个对象时不向客户暴露内部细节&#xff0c;并提供一个创建对象的通用接口。 说明&#xff1a; 简单工厂把实例化的操作单独放到一个类中&#xff0c;这个类就成为简单工厂类&#xff0c;让简单工厂类来决定应该用哪…...

ffmpeg拉流分段存储到文件-笔记

通过ffmpeg可以从rtsp网络流拉取数据并存储到本地文件里&#xff0c;如下命令。做个笔记 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 流中捕获视频&#xff…...

Java 实习工资大概是多少?——解读影响薪资的因素

文章目录 1. 城市因素&#xff1a;一线、二线的差距2. 公司类型&#xff1a;互联网公司、外企和传统企业的差别3. 个人能力&#xff1a;经验、技术栈的重要性4. 其他影响因素&#xff1a;学历和实习时间总结推荐阅读文章 Java 开发作为广泛应用的职业方向&#xff0c;实习工资的…...

【Linux】万字详解:Linux文件系统与软硬链接

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 &#x1f680; 前言 一&#xff1a; &#x1f525; 磁盘的物理结构二&#xff1a; &#x1f525; 磁盘的存储结构 三&#xff1a; &#x1f525; 磁盘的逻辑结构 四&#xff1a; &#…...

spacenavd

介绍spacenavd开源项目&#xff0c;主要是因为在斯坦福大学的UMI项目中使用了该项目。在斯坦福大学的 UMI&#xff08;Universal Manipulation Interface&#xff09;项目中&#xff0c;Spacenavd 主要用于处理 3D Space Mouse&#xff08;空间鼠标&#xff09;的输入&#xf…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...