写点什么

新项目为什么决定用 JDK 17 了

作者:古时的风筝
  • 2022-12-20
    北京
  • 本文字数:2876 字

    阅读完需:约 9 分钟

新项目为什么决定用 JDK 17了

大家好,我是风筝。公众号「古时的风筝」,文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在里面。


最近在调研 JDK 17,并且试着将之前的一个小项目升级了一下,在测试环境跑了一段时间。最终,决定了,新项目要采用 JDK 17 了。


JDK 1.8:“不是说好了,他发任他发,你用 Java 8 吗?”


不光是我呀,连 Spring Boot 都开始要拥护 JDK 17 了,下面这一段是 Spring Boot 3.0 的更新日志。


Spring Boot 3.0 requires Java 17 as a minimum version. If you are currently using Java 8 or Java 11, you'll need to upgrade your JDK before you can develop Spring Boot 3.0 applications.


Spring Boot 3.0 需要 JDK 的最低版本就是 JDK 17,如果你想用 Spring Boot 开发应用,你需要将正在使用的 Java 8 或 Java 11 升级到 Java 17。


选用 Java 17,概括起来主要有下面几个主要原因:


1、JDK 17 是 LTS (长期支持版),可以免费商用到 2029 年。而且将前面几个过渡版(JDK 9-JDK 16)去其糟粕,取其精华的版本;


2、JDK 17 性能提升不少,比如重写了底层 NIO,至少提升 10% 起步;


3、大多数第三方框架和库都已经支持,不会有什么大坑;


4、准备好了,来吧。


拿几个比较好玩儿的特性来说一下 JDK 17 对比 JDK 8 的改进。

密封类

密封类应用在接口或类上,对接口或类进行继承或实现的约束,约束哪些类型可以继承、实现。例如我们的项目中有个基础服务包,里面有一个父类,但是介于安全性考虑,值允许项目中的某些微服务模块继承使用,就可以用密封类了。


没有密封类之前呢,可以用 final关键字约束,但是这样一来,被修饰的类就变成完全封闭的状态了,所有类都没办法继承。


密封类用关键字 sealed修饰,并且在声明末尾用 permits表示要开放给哪些类型。


下面声明了一个叫做 SealedPlayer的密封类,然后用关键字 permits将集成权限开放给了 MarryPlayer类。


public sealed class SealedPlayer permits MarryPlayer {    public void play() {        System.out.println("玩儿吧");    }}
复制代码


之后 MarryPlayer 就可以继承 SealedPlayer了。


public non-sealed class MarryPlayer extends SealedPlayer{    @Override    public void play() {        System.out.println("不想玩儿了");    }}
复制代码


继承类也要加上密封限制。比如这个例子中是用的 non-sealed,表示不限制,任何类都可以继承,还可以是 sealed,或者 final


如果不是 permits 允许的类型,则没办法继承,比如下面这个,编译不过去,会给出提示 "java: 类不得扩展密封类:org.jdk17.SealedPlayer(因为它未列在其 'permits' 子句中)"


public non-sealed class TomPlayer extends SealedPlayer {
@Override public void play() {
}}
复制代码

空指针异常

String s = null;String s1 = s.toLowerCase();
复制代码


JDK1.8 的版本下运行:


Exception in thread "main" java.lang.NullPointerException  at org.jdk8.App.main(App.java:10)
复制代码


JDK17 的版本(确切的说是 14 及以上版本)


Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.toLowerCase()" because "s" is null  at org.jdk17.App.main(App.java:14)
复制代码


出现异常的具体方法和原因都一目了然。如果你的一行代码中有多个方法、多个变量,可以快速定位问题所在,如果是 JDK1.8,有些情况下真的不太容易看出来。

yield 关键字

public static int calc(int a,String operation){    var result = switch (operation) {        case "+" -> {            yield a + a;        }        case "*" -> {            yield a * a;        }        default -> a;    };    return result;}
复制代码

换行文本块

如果你用过 Python,一定知道 Python 可以用 'hello world'"hello world"''' hello world '''""" hello world """ 四种方式表示一个字符串,其中后两种是可以直接支持换行的。


在 JDK 1.8 中,如果想声明一个字符串,如果字符串是带有格式的,比如回车、单引号、双引号,就只能用转义符号,例如下面这样的 JSON 字符串。


String json = "{\n" +        "  \"name\": \"古时的风筝\",\n" +        "  \"age\": 18\n" +        "}";
复制代码


从 JDK 13 开始,也像 Python 那样,支持三引号字符串了,所以再有上面的 JSON 字符串的时候,就可以直接这样声明了。


String json = """        {          "name": "古时的风筝",          "age": 18        }        """;
复制代码

record 记录类

类似于 Lombok 。


传统的 Java 应用程序通过创建一个类,通过该类的构造方法实例化类,并通过 getter 和 setter 方法访问成员变量或者设置成员变量的值。有了 record 关键字,你的代码会变得更加简洁。


之前声明一个实体类。


public class User {    private String name;
public String getName() { return name; } public void setName(String name) { this.name = name; }}
复制代码


使用 Record类之后,就像下面这样。


public record User(String name) {
}
复制代码


调用的时候像下面这样


RecordUser recordUser = new RecordUser("古时的风筝");System.out.println(recordUser.name());System.out.println(recordUser.toString());
复制代码


输出结果



Record 类更像是一个实体类,直接将构造方法加在类上,并且自动给字段加上了 getter 和 setter。如果一直在用 Lombok 或者觉得还是显式的写上 getter 和 setter 更清晰的话,完全可以不用它。

G1 垃圾收集器

JDK8 可以启用 G1 作为垃圾收集器,JDK9 到 JDK 17,G1 垃圾收集器是默认的垃圾收集器,G1 是兼顾老年代和年轻代的收集器,并且其内存模型和其他垃圾收集器是不一样的。


G1 垃圾收集器在大多数场景下,其性能都好于之前的垃圾收集器,比如 CMS。

ZGC

从 JDk 15 开始正式启用 ZGC,并且在 JDK 16 后对 ZGC 进行了增强,控制 stop the world 时间不超过 10 毫秒。但是默认的垃圾收集器仍然是 G1。


配置下面的参数来启用 ZGC 。


-XX:+UseZGC
复制代码


可以用下面的方法查看当前所用的垃圾收集器


JDK 1.8 的方法


jmap -heap 8877
复制代码


JDK 1.8 以上的版本


jhsdb jmap --heap --pid 8877
复制代码


例如下面的程序采用 ZGC 垃圾收集器。


其他一些小功能

1、支持 List.of()、Set.of()、Map.of()和 Map.ofEntries()等工厂方法实例化对象;


2、Stream API 有一些改进,比如 .collect(Collectors.toList())可以直接写成 .toList()了,还增加了 Collectors.teeing(),这个挺好玩,有兴趣可以看一下;


3、HttpClient重写了,支持 HTTP2.0,不用再因为嫌弃 HttpClient 而使用第三方网络框架了,比如 OKHTTP;

升级 JDK 和 IDEA

安装 JDK 17,这个其实不用说,只是推荐一个网站,这个网站可以下载各种系统、各种版本的 JDK 。地址是 https://adoptium.net/


还有,如果你想在 IDEA 上使用 JDK 17,可能要升级一下了,只有在 2021.02版本之后才支持 JDK 17。


各位爱学习的同学,赶紧试一下吧。


公众号「古时的风筝」,Java 开发者,bug 杀手,擅长解决问题。

坚持原创干货输出,你可选择现在就关注我,或者看看历史文章再关注也不迟。长按二维码关注,跟我一起变优秀!



发布于: 刚刚阅读数: 3
用户头像

种一棵树最好的时间是十年前,其次是现在 2017-09-10 加入

公众号:古时的风筝。一个本打算写诗却写起了代码的田园码农。

评论

发布
暂无评论
新项目为什么决定用 JDK 17了_Java_古时的风筝_InfoQ写作社区