大家好呀,我是summo,JDK版本升级的非常快,现在已经到JDK20了。JDK版本虽多,但应用最广泛的还得是JDK8,正所谓“他发任他发,我用Java8”。

其实我也不太想升级JDK版本,感觉投入高,收益小,不过有一次我看到了一些使用JDK17新语法写的代码,让我改变了对升级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返回HTML文本
*
* @return 返回HTML文本
*/
public static final String getHtmlJDK17() {
return """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
}

推荐指数:️️️️️

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();
}
}

运行结果

推荐指数:️️️️️

3. Records

在Java中,POJO对象(如DO、PO、VO、DTO等)通常包含成员变量及相应的Getter和Setter方法。尽管可以通过工具或IDE生成这些代码,但修改和维护仍然麻烦。Lombok插件为此出现,能够在编译期间自动生成Getter、Setter、hashcode、equals和构造函数等代码,使用起来方便,但对团队有依赖要求。

为此,Java引入了标准解决方案:Records。它通过简洁的语法定义数据类,大大简化了POJO类的编写,如下所示。虽然hashcode和equals方法仍需手动编写,但IDE能够自动生成。这一特性有效解决了模板代码问题,提升了代码整洁度和可维护性。

package com.summo.jdk17;

/**
* 3星
*
* @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);
}
}

推荐指数:️️️️

4. 全新的switch表达式

有人可能问了,Java语言不早已支持switch了嘛,有什么好提的?讲真,这次的提升还真有必要好好地来聊一聊了。在Java12的时候就引入了switch表达式,注意这里是表达式,而不是语句,原来的switch是语句。如果不清楚两者的区别的话,最好先去了解一下。主要的差别就是就是表达式有返回值,而语句则没有。再配合模式匹配,以及yield和“->”符号的加入,全新的switch用起来爽到飞起来。

package com.summo.jdk17;

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
}
}

推荐指数:️️️️

5. 私有接口方法

从Java8开始,允许在interface里面添加默认方法,其实当时就有些小困惑,如果一个default方法体很大怎么办,拆到另外的类去写吗?实在有些不太合理,所以在Java17里面,如果一个default方法体很大,那么可以通过新增接口私有方法来进行一个合理的拆分了,为这个小改进点个赞。

public interface PrivateInterfaceMethod {
    /**
     * 接口默认方法
     */
    default void defaultMethod() {
        privateMethod();
    }     // 接口私有方法,在Java8里面是不被允许的,不信你试试
    private void privateMethod() {
    }
}

推荐指数:️️️

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());
}
}

新的写法

/**
* 转换并申请了一个新的变量,极大地方便了代码的编写
*
* @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());
}
}

推荐指数:️️️️

7. 集合类的工厂方法

在Java8的年代,即便创建一个很小的集合,或者固定元素的集合都是比较麻烦的,为了简洁一些,有时我甚至会引入一些依赖。

原来的写法

Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c"

新的写法

Set<String> set = Set.of("a", "b", "c");

推荐指数:️️️️️

二、其他的新特性

1. 新的String方法

  • repeat:重复生成字符串
  • isBlank:不用在引入第三方库就可以实现字符串判空了
  • strip:去除字符串两边的空格,支持全角和半角,之前的trim只支持半角
  • lines:能根据一段字符串中的终止符提取出行为单位的流
  • indent:给字符串做缩进,接受一个int型的输入
  • transform:接受一个转换函数,实现字符串的转换

2. 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));

3. jshell

在新的JDK版本中,支持直接在命令行下执行java程序,类似于python的交互式REPL。简而言之,使用 JShell,你可以输入代码片段并马上看到运行结果,然后就可以根据需要作出调整,这样在验证一些简单的代码的时候,就可以通过jshell得到快速地验证,非常方便。

4. java命令直接执行java文件

在现在可以直接通过执行“java xxx.java”,即可运行该java文件,无须先执行javac,然后再执行java,是不是又简单了一步。

5. ZGC

在ParallelOldGC、CMS和G1之后,JDK 11引入了全新的ZGC(Z Garbage Collector)。这个名字本身就显得很牛。官方宣称ZGC的垃圾回收停顿时间不超过10ms,能支持高达16TB的堆空间,并且停顿时间不会随着堆的增大而增加。那么,ZGC到底解决了什么问题?Oracle官方介绍它是一个可伸缩的低延迟垃圾回收器,旨在降低停顿时间,尽管这可能会导致吞吐量的降低。不过,通过横向扩展服务器可以解决吞吐量问题。官方已建议ZGC可用于生产环境,这无疑将成为未来的主流垃圾回收器。要了解更多,请参阅官方文档

三、小结一下

作为程序员,持续学习和充电非常重要。随着Java8即将停止免费官方支持,越来越多的项目将转向Java17,包括大名鼎鼎的Spring Boot 3.0,它在2022年1月20日发布的第一个里程碑版本(M1)正是基于Java17构建的。该项目依赖的所有组件也将快速升级,未来如果想利用某些新特性,在Java8下将无法通过编译.,到这时候再换就真的晚了... ...

我有点想用JDK17了的更多相关文章

  1. JDK8到JDK17有哪些吸引人的新特性?

    作者:京东零售 刘一达 前言 2006年之后SUN公司决定将JDK进行开源,从此成立了OpenJDK组织进行JDK代码管理.任何人都可以获取该源码,并通过源码构建一个发行版发布到网络上.但是需要一个组 ...

  2. 看完SQL Server 2014 Q/A答疑集锦:想不升级都难!

    看完SQL Server 2014 Q/A答疑集锦:想不升级都难! 转载自:http://mp.weixin.qq.com/s/5rZCgnMKmJqeC7hbe4CZ_g 本期嘉宾为微软技术中心技术 ...

  3. CoreCRM 开发实录——想用国货不容易

    昨天(2016年12月29日)发了开始开发的文章.本来晚上准备在 Coding.NET 上添加几个任务开始搞起了.可是真的开始用的时候才发现:Coding.NET 的任务功能只针对私有的任务开放.我想 ...

  4. 【踩坑速记】二次依赖?android studio编译运行各种踩坑解决方案,杜绝弯路,总有你想要的~

    这篇博客,只是把自己在开发中经常遇到的打包编译问题以及解决方案给大家稍微分享一下,不求吸睛,但求有用. 1.大家都知道我们常常会遇到dex超出方法数的问题,所以很多人都会采用android.suppo ...

  5. 要想提高PHP的编程效率,你必须知道的要点

    1.当操作字符串并需要检验其长度是否满足某种要求时,你想当然地会使用strlen()函数.此函数执行起来相当快,因为它不做任何计算,只返回在zval 结构(C的内置数据结构,用于存储PHP变量)中存储 ...

  6. 我想立刻辞职,然后闭关学习编程语言,我给自己3个月时间学习C语言!这样行的通吗

    文章背景,回答提问:我想立刻辞职,然后闭关学习编程语言,我给自己3个月时间学习C语言!这样行的通吗? 我的建议是这样:1. 不要辞职.首先说,你对整个开发没有一个简单的了解,或一个系统的入门学习.换句 ...

  7. ES6 箭头函数中的 this?你可能想多了(翻译)

    箭头函数=>无疑是ES6中最受关注的一个新特性了,通过它可以简写 function 函数表达式,你也可以在各种提及箭头函数的地方看到这样的观点——“=> 就是一个新的 function”. ...

  8. Windbg Extension NetExt 使用指南 【3】 ---- 挖掘你想要的数据 Managed Heap

    摘要 : NetExt中有两个比较常用的命令可以用来分析heap上面的对象. 一个是!wheap, 另外一个是!windex. !wheap 这个命令可以用于打印出heap structure信息. ...

  9. JS的Object漫想:从现象到“本质”

    转自:http://zzy603.iteye.com/blog/973649 写的挺好,用于记录,把对象分成概念的Object(var f={})和 类的Object(function F(){}) ...

  10. 个人随想:对于一个.Neter来说,如果一直想走技术路线,该怎么走下去

    前言 首先我不是一个合格的.Neter,也许在这里我的技术算是很菜的,不过我也是有想法的人,下面罗列出我的想法和将要实现的技术路线图. 1.学习一门底层语言 比如学习C语言,学习C语言的最终目的我觉得 ...

随机推荐

  1. echarts使用与踩坑

    0.踩坑点 1.当图表不显示在页面(display:none)执行resize可能会导致图表样式混乱 1. 官网示例 import * as echarts from 'echarts'; // 基于 ...

  2. OpenYurt v1.1.0: 新增 DaemonSet 的 OTA 和 Auto 升级策略

    简介: 在 OpenYurt v1.1.0 版本中,我们提供了 Auto 和 OTA 的升级策略.Auto 的升级策略重点解决由于节点 NotReady 而导致 DaemonSet升级阻塞的问题,OT ...

  3. 从KPI到OKR,高阶产品人如何推动业务高速增长

    简介: 不管是核心大目标,还是O(Objectives),或者北极星指标,奇妙等式等等,最后都需要核心组织协同方式来推动整个目标聚焦以及过程的落地. 作为产品经理人,相信很多人都遇到过以下的灵魂拷问: ...

  4. 云原生时代如何用 Prometheus 实现性能压测可观测-Metrics 篇

    ​简介:可观测性包括 Metrics.Traces.Logs3 个维度.可观测能力帮助我们在复杂的分布式系统中快速排查.定位问题,是分布式系统中必不可少的运维工具. 作者:拂衣 什么是性能压测可观测 ...

  5. Serverless 场景下 Pod 创建效率优化

    简介: 众所周知,Kubernetes 是云原生领域的基石,作为容器编排的基础设施,被广泛应用在 Serverless 领域.弹性能力是 Serverless 领域的核心竞争力,本次分享将重点介绍基于 ...

  6. 最佳实践丨构建云上私有池(虚拟IDC)的5种方案详解

    ​简介:云上私有池系列终篇终于来了,本文将重点介绍构建云上的私有池(虚拟IDC)的多种方案和各自的优缺点,并给出相关的性价比优化建议. 本文作者:阿里云技术专家李雨前 摘要 围绕私有池(虚拟IDC)的 ...

  7. 来电科技:基于 Flink + Hologres 的实时数仓演进之路

    简介: 本文将会讲述共享充电宝开创企业来电科技如何基于 Flink + Hologres 构建统一数据服务加速的实时数仓 作者:陈健新,来电科技数据仓库开发工程师,目前专注于负责来电科技大数据平台离线 ...

  8. Python编程的若干个经典小技巧

    1. 原地交换两个数字 Python 提供了一个直观的在一行代码中赋值与交换(变量值)的方法,请参见下面的示例: x,y= 10,20 print(x,y) x,y= y,x print(x,y) # ...

  9. [FAQ] gormV2 Too many connections

    gormV2 中不再有v1的 db.Close() 方法. 取而代之的 close 方式是如下: sqlDB, err := DB.DB() sqlDB.Close() https://github. ...

  10. vue中使用vue-b2wordcloud创建词云

    安装使用 安装:使用npm install vue-b2wordcloud --save或者直接在vue ui中添加vue-b2wordcloud运行依赖 使用:在main.js中导入使用 impor ...