JDK17 新特性
引言
JDK 版本升级的非常快,写这篇博客时已经到 JDK22 了,而 Java 17 继续作为业界最常用的长期支持(LTS)版本。目前 Java 11 是最受欢迎的LTS 版本,有超过 56% 的应用程序在生产中使用它,而 Java 8 的使用率为 33% 且逐年下降,Java 17 的使用率在一年内增长了 430 %,有超过9%的应用程序在生产中使用 Java 17。
简言之,JDK11(当前主流)、JDK8(逐渐淘汰)、JDK17(未来趋势)
作为 Java 初学者,学习时建议使用当前主流或更高一些的 JDK 版本,这样可以学习和体验 JDK 新特性带来的便利,也为未来从事生产应用开发积累经验。
JDK17新特性1 - 文本块(推荐指数:️️️️️)
这个更新非常实用。在没有这个特性之前,编写长文本非常痛苦。虽然 IDEA 等集成开发工具可以自动处理,但最终效果仍然丑陋,充满拼接符号。现在,通过字符串块,我们可以轻松编写JSON、HTML、SQL等内容,效果更清爽。
这个新特性值得五颗星评价,因为它让我们只需关注字符串本身,而无需关心拼接操作。
之前写法如下:
/**
* 使用JDK8返回HTML文本
*
* @return 返回HTML文本
*/
public static final String getHtmlJDK8() {
return "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>";
}
JDK17写法如下:
/**
* 使用JDK17返回HTML文本
* @return 返回HTML文本
*/
public static final String getHtmlJDK17() {
return """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
}
JDK17新特性2 - NullPointerException 增强(推荐指数:️️️️️)
这一功能非常强大且实用,相信每位 Java 开发者都期待已久。空指针异常(NPE)一直是Java程序员的痛点,因为报错信息无法直观地指出哪个对象为空,只抛出一个 NullPointerException 和一堆堆栈信息,定位问题耗时且麻烦。尤其在遇到喜欢级联调用的代码时,逐行排查更是令人头疼。如果在测试环境中,可能还需通过远程调试查明空对象,费时费力。为此,阿里的编码规范甚至不允许级联调用,但这并不能彻底解决问题。Java17 终于在这方面取得了突破,提供了更详细的空指针异常信息,帮助开发者迅速定位问题源头。
使用举例:
public static void main(String[] args) {
try {
//简单的空指针
String str = null;
str.length();
} catch (Exception e) {
e.printStackTrace();
}
try {
//复杂一点的空指针
var arr = List.of(null);
String str = (String)arr.get(0);
str.length();
} catch (Exception e) {
e.printStackTrace();
}
}
运行结果

JDK17新特性3 - Records(推荐指数:️️️️)
在Java中,POJO对象(如DO、PO、VO、DTO等)通常包含成员变量及相应的Getter和Setter方法。尽管可以通过工具或IDE生成这些代码,但修改和维护仍然麻烦。Lombok 插件为此出现,能够在编译期间自动生成Getter、Setter、hashcode、equals和构造函数等代码,使用起来方便,但对团队有依赖要求。为此,Java引入了标准解决方案:Records。它通过简洁的语法定义数据类,大大简化了POJO类的编写,如下所示。虽然hashcode和equals方法仍需手动编写,但IDE能够自动生成。这一特性有效解决了模板代码问题,提升了代码整洁度和可维护性。
使用举例
/**
*
* @param stuId 学生ID
* @param stuName 学生名称
* @param stuAge 学生年龄
* @param stuGender 学生性别
* @param stuEmail 学生邮箱
*/
public record StudentRecord(Long stuId,
String stuName,
int stuAge,
String stuGender,
String stuEmail) {
public StudentRecord {
System.out.println("构造函数");
}
public static void main(String[] args) {
StudentRecord record = new StudentRecord(1L, "张三", 16, "男", "xxx@qq.com");
System.out.println(record);
}
}
JDK17新特性4 - 全新的switch表达式(推荐指数:️️️️)
在 Java12 的时候就引入了switch表达式,注意这里是表达式,而不是语句,原来的switch是语句。如果不清楚两者的区别的话,最好先去了解一下。主要的差别就是就是表达式有返回值,而语句则没有。再配合模式匹配,以及yield和“->”符号的加入,全新的switch用起来爽到飞起来。
使用举例
public class SwitchDemo {
/**
* 在JDK8中获取switch返回值方式
*
* @param week
* @return
*/
public int getByJDK8(Week week) {
int i = 0;
switch (week) {
case MONDAY, TUESDAY:
i = 1;
break;
case WEDNESDAY:
i = 3;
break;
case THURSDAY:
i = 4;
break;
case FRIDAY:
i = 5;
break;
case SATURDAY:
i = 6;
break;
case SUNDAY:
i = 7;
break;
default:
i = 0;
break;
}
return i;
}
/**
* 在JDK17中获取switch返回值
*
* @param week
* @return
*/
public int getByJDK17(Week week) {
// 1, 现在的switch变成了表达式,可以返回值了,而且支持yield和->符号来返回值
// 2, 再也不用担心漏写了break,而导致出问题了
// 3, case后面支持写多个条件
return switch (week) {
case null -> -1;
case MONDAY -> 1;
case TUESDAY -> 2;
case WEDNESDAY -> 3;
case THURSDAY -> {yield 4;}
case FRIDAY -> 5;
case SATURDAY, SUNDAY -> 6;
default -> 0;
};
}
private enum Week {
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
}
JDK17新特性5 - 私有接口方法(推荐指数:️️️)
从Java8开始,允许在interface里面添加默认方法,其实当时就有些小困惑,如果一个default方法体很大怎么办,拆到另外的类去写吗?实在有些不太合理,所以在Java17里面,如果一个default方法体很大,那么可以通过新增接口私有方法来进行一个合理的拆分了,为这个小改进点个赞。
使用举例
public interface PrivateInterfaceMethod {
/**
* 接口默认方法
*/
default void defaultMethod() {
privateMethod();
}
// 接口私有方法,在Java8里面是不被允许的,不信你试试
private void privateMethod() {
}
}
JDK17新特性6 - 模式匹配(推荐指数:️️️️)
在JDK 17中,模式匹配主要用于instanceof表达式。模式匹配增强了instanceof的语法和功能,使类型检查和类型转换更加简洁和高效。在传统的Java版本中,我们通常使用instanceof结合类型转换来判断对象类型并进行处理,这往往会导致冗长的代码。
以前的写法如下:
/**
* 旧式写法
*
* @param value
*/
public void matchByJDK8(Object value) {
if (value instanceof String) {
String v = (String)value;
System.out.println("遇到一个String类型" + v.toUpperCase());
} else if (value instanceof Integer) {
Integer v = (Integer)value;
System.out.println("遇到一个整型类型" + v.longValue());
}
}
JDK17的写法如下:
/**
* 转换并申请了一个新的变量,极大地方便了代码的编写
*
* @param value
*/
public void matchByJDK17(Object value) {
if (value instanceof String v) {
System.out.println("遇到一个String类型" + v.toUpperCase());
} else if (value instanceof Integer v) {
System.out.println("遇到一个整型类型" + v.longValue());
}
}
JDK17新特性7 - 集合类的工厂方法(推荐指数:️️️️️)
在Java8的年代,即便创建一个很小的集合,或者固定元素的集合都是比较麻烦的,为了简洁一些,有时我甚至会引入一些依赖。
以前的写法如下:
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
JDK17的写法如下:
Set<String> set = Set.of("a", "b", "c");
JDK17其他新特性
新的String方法
- repeat:重复生成字符串
- isBlank:不用在引入第三方库就可以实现字符串判空了
- strip:去除字符串两边的空格,支持全角和半角,之前的trim只支持半角
- lines:能根据一段字符串中的终止符提取出行为单位的流
- indent:给字符串做缩进,接受一个int型的输入
- transform:接受一个转换函数,实现字符串的转换
Stream API的增强
增加takeWhile, dropWhile, ofNullable, iterate以及toList的API,越来越像一些函数式语言了。
用法举例
// takeWhile 顺序返回符合条件的值,直到条件不符合时即终止继续判断,
// 此外toList方法的加入,也大大减少了节省了代码量,免去了调用collect(Collectors::toList)方法了
List<Integer> list = Stream.of(2,2,3,4,5,6,7,8,9,10)
.takeWhile(i->(i%2==0)).toList(); // 返回2, 2
// dropWhile 顺序去掉符合条件的值,直到条件不符合时即终止继续判断
List<Integer> list1 = Stream.of(2,2,3,4,5,6,7,8,9,10)
.dropWhile(i->(i%2==0)).toList(); //返回3, 4, 5, 6, 7, 8, 9, 10
// ofNullable,支持传入空流,若没有这个且传入一个空流,那么将会抛NPE
var nullStreamCount = Stream.ofNullable(null).count(); //返回0
// 以下两行都将输出0到9
Stream.iterate(0, n -> n < 10, n -> n + 1).forEach(x -> System.out.println(x));
Stream.iterate(0, n -> n + 1).limit(10).forEach(x -> System.out.println(x));
全新的HttpClient
这个API首次出现在9之中,不过当时并非是一个稳定版本,在Java11中正式得到发布,所以在Java17里面可以放心地进行使用。原来的JDK自带的Http客户端真的非常难用,这也就给了很多像okhttp、restTemplate、Apache的HttpClient和feign这样的第三方库极大的发挥空间,几乎就没有人愿意去用原生的Http客户端的。但现在不一样了,感觉像是新时代的API了。FluentAPI风格,处处充满了现代风格,用起来也非常地方便,再也不用去依赖第三方的包了,就两个字,清爽。
// 同步请求
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_1_1)
.followRedirects(Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(20))
.proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
.authenticator(Authenticator.getDefault())
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
// 异步请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://foo.com/"))
.timeout(Duration.ofMinutes(2))
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofFile(Paths.get("file.json")))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
jshell
在新的JDK版本中,支持直接在命令行下执行java程序,类似于python的交互式REPL。简而言之,使用 JShell,你可以输入代码片段并马上看到运行结果,然后就可以根据需要作出调整,这样在验证一些简单的代码的时候,就可以通过jshell得到快速地验证,非常方便。
java命令直接执行java文件
在现在可以直接通过执行java xxx.java,即可运行该java文件,无须先执行javac,然后再执行java,是不是又简单了一步。
ZGC
在ParallelOldGC、CMS和G1之后,JDK 11引入了全新的ZGC(Z Garbage Collector)。这个名字本身就显得很牛。官方宣称ZGC的垃圾回收停顿时间不超过10ms,能支持高达16TB的堆空间,并且停顿时间不会随着堆的增大而增加。
那么,ZGC到底解决了什么问题?Oracle官方介绍它是一个可伸缩的低延迟垃圾回收器,旨在降低停顿时间,尽管这可能会导致吞吐量的降低。不过,通过横向扩展服务器可以解决吞吐量问题。官方已建议ZGC可用于生产环境,这无疑将成为未来的主流垃圾回收器。
要了解更多,请参阅官方文档
https://docs.oracle.com/en/java/javase/17/gctuning/z-garbage-collector.html#GUID-9957D441-A99A-4CF5-9522-393E6DE7D898
JDK17 新特性的更多相关文章
- JDK8到JDK17有哪些吸引人的新特性?
作者:京东零售 刘一达 前言 2006年之后SUN公司决定将JDK进行开源,从此成立了OpenJDK组织进行JDK代码管理.任何人都可以获取该源码,并通过源码构建一个发行版发布到网络上.但是需要一个组 ...
- 各版本JDK1.5-1.8新特性
概述 一jdk15新特性 泛型 foreach 自动拆箱装箱 枚举 静态导入Static import 元数据Metadata 线程池 Java Generics 二jdk16新特性 Desktop类 ...
- Java9-17新特性一览,了解少于3个你可能脱节了
前言 Java8出来这么多年后,已经成为企业最成熟稳定的版本,相信绝大部分公司用的还是这个版本,但是一眨眼今年Java19都出来了,相信很多Java工程师忙于学习工作对新特性没什么了解,有的话也仅限于 ...
- Java9至17的新特性总结
总览 讲讲Java 9-17 的一些语法糖和一些新发布的jeps, 重点讲讲JVM的垃圾回收器 时间线 SpringBoot 为什么选择Java17这个版本.我估计跟下面这个图有关系. Java 8 ...
- JDK19新特性使用详解
前提 JDK19于2022-09-20发布GA版本,本文将会详细介绍JDK19新特性的使用. 新特性列表 新特性列表如下: JPE-405:Record模式(预览功能) JPE-422:JDK移植到L ...
- SQL Server 2014 新特性——内存数据库
SQL Server 2014 新特性——内存数据库 目录 SQL Server 2014 新特性——内存数据库 简介: 设计目的和原因: 专业名词 In-Memory OLTP不同之处 内存优化表 ...
- ElasticSearch 5学习(10)——结构化查询(包括新特性)
之前我们所有的查询都属于命令行查询,但是不利于复杂的查询,而且一般在项目开发中不使用命令行查询方式,只有在调试测试时使用简单命令行查询,但是,如果想要善用搜索,我们必须使用请求体查询(request ...
- [干货来袭]C#6.0新特性
微软昨天发布了新的VS 2015 ..随之而来的还有很多很多东西... .NET新版本 ASP.NET新版本...等等..太多..实在没消化.. 分享一下也是昨天发布的新的C#6.0的部分新特性吧.. ...
- CSS3新特性应用之结构与布局
一.自适应内部元素 利用width的新特性min-content实现 width新特性值介绍: fill-available,自动填充盒子模型中剩余的宽度,包含margin.padding.borde ...
- 【译】Meteor 新手教程:在排行榜上添加新特性
原文:http://danneu.com/posts/6-meteor-tutorial-for-fellow-noobs-adding-features-to-the-leaderboard-dem ...
随机推荐
- C# 将 CSV 转化为 Excel
引言 在数据处理和交换的过程中,CSV(逗号分隔值)格式和 Excel 文件格式都是非常常见的.CSV 文件以纯文本形式存储表格数据,易于生成和处理:而 Excel 文件则提供了更丰富的功能,如数据可 ...
- Dify发布V1.5.0:可视化故障排查!超实用
Dify 本周又发布了一个实用的大版本,直接从 V1.4.3 版本干到 V1.5.0 了,那问题来了,这次更新了哪些内容呢?接下来我们一起来看. 官方给这次更新的定义是:一个简洁.强大的更新,通过简化 ...
- tgt源码阅读
读懂一个开源项目源码之前,需要先了解该项目的背景知识.背景知识熟悉了,代码只是具体实现手段而已. 源码地址:https://github.com/fujita/tgt 对于tgt来说,背景知识是块设备 ...
- AI应用实战课学习总结(4)医疗数据可视化
大家好,我是Edison. 最近入坑黄佳老师的<AI应用实战课>,记录下我的学习之旅,也算是总结回顾. 今天是我们的第4站,通过一个经典的医疗数据集来进行数据可视化的实战. 数据集介绍 这 ...
- C# 的深度强化学习框架RL_Matrix
一.RL_Matrix 项目概述 RL_Matrix 是一个专为 .NET 开发者设计的强化学习框架,使用 TorchSharp(.NET 版的 PyTorch)作为后端,提供类型安全.高性能的环境, ...
- 如何用三层防护体系打造坚不可摧的 API 安全堡垒?
扫描二维码 关注或者微信搜一搜:编程智域 前端至全栈交流与成长 发现1000+提升效率与开发的AI工具和实用程序:https://tools.cmdragon.cn/ FastAPI 安全与认证综合实 ...
- C# dataTable 操作 上移 下移
https://blog.csdn.net/CSDN2016DDDD/article/details/80226755 上移:DataRow newdata = dt.NewRow();newdata ...
- SqlServer查看某个表的索引详细信息
SELECT TableId=O.[object_id], TableName=O.Name, IndexId=ISNULL(KC.[object_id],IDX.index_id), IndexNa ...
- 探索 MCP C# SDK:实现大语言模型与应用的无缝对接
探索 MCP C# SDK:实现大语言模型与应用的无缝对接 在当今人工智能快速发展的时代,大语言模型(LLMs)已经成为众多应用的核心驱动力.然而,如何让这些强大的模型与各种数据源和工具进行有效集成, ...
- 探讨医疗大模型创业CEO面临的行业困境与前景-九五小庞
要点: - 医疗大模型行业发展迅速,但技术仍需完善,尤其在图像处理和文本领域. - 企业主要使用开源模型,通过数据增强和微调进行训练,但在模型架构上无显著改进. - 投资人质疑盈利模式,对医疗大模型公 ...