Java11及Java17新特性体验总结
目前工作中用的版本还是JAVA8,现在JAVA版本发布太快,目前已经有11和17两个LTS版本。从JDK1.8开始,Oracle的JDK 付费政策 就一直被人诟病,但是从17开始,Oracle宣布推出JDK免费服务。并且Spring 已经宣布计划在22年4季度发布的Spring Framework 6 和Spring Boot 3要求的最低版本就是17,所以是时候可以开始尝试一下新版本了。
PS:先更新一下,22年9月发布的JDK19中,终于推出了重磅新特性:虚拟线程。虽然19还不是LTS版本,并且虚拟线程也还处于预览阶段,但是还是非常期待在下个正式版本中能够见到。先简单补一下19的新特性吧,详细体验找时间在补上…….()
首先看下JAVA8以后几个主要版本发布时间以及主要特性。
版本 | 发布时间 | 主要特性 |
---|---|---|
JAVA SE 8 (LTS) | 2014 年 3 月 | lambada表达式 函数式接口 方法引用 默认方法 Stream API 对元素流进行函数式操作 Optional 解决NullPointerException Date Time API 重复注解 @Repeatable Base64 使用元空间Metaspace代替持久代(PermGen space) |
JAVA 11 (LTS) | 2018 年 9 月 | 增加一些符串处理方法 用于 Lambda 参数的局部变量语法 Http Client重写,支持HTTP/1.1和HTTP/2 ,也支持 websockets 可运行单一Java源码文件,如:java Test.java ZGC:可伸缩低延迟垃圾收集器 支持 TLS 1.3 协议 |
JAVA 17 (LTS) | 2021 年 9 月 | Free Java License JDK 17 将取代 JDK 11 成为下一个长期支持版本 Spring 6 和 Spring Boot 3需要JDK17 移除实验性的 AOT 和 JIT 编译器 恢复始终执行严格模式 (Always-Strict) 的浮点定义 |
JAVA 19 | 2022年9月 | Record 模式匹配 (预览) 虚拟线程 (预览) Switch 模式匹配(第三次预览) Linux/RISC-V Port Vector API (四次孵化) 外部函数和内存 API (预览) 结构化并发(孵化) |
JAVA 20 | 2022年3月 | Record Patterns(记录模式)(预览) Linux/RISC-V Port Foreign Function & Memory API(外部函数和内存 API)(预览) Virtual Threads(虚拟线程)(预览) Vector(向量)API(第四次孵化) Pattern Matching for switch(switch 模式匹配) Structured Concurrency(结构化并发)(孵化) |
从JAVA9开始,为了更快地迭代,以及跟进社区反馈,Oracle的开始使用新的发行节奏,半年一个小版本,每三年一个大版本,并且承诺不会跳票,以免出现类似JAVA9那样多次延迟发布的尴尬局面。最近一个LTS版本是2021 年 9 月, 发布的 JAVA 17。
虽然目前大部分公司日常开发使用的还是JAVA8,不过还是需要多了解一下新版本的特性。首先在新的版本发布模式下,大多数变更首先需要经过“预览”阶段,也就是说它们被添加到一个版本中,但还没有完成。人们可以尝试使用它们,但不建议将其用在生产环境中。接下来代码示例中使用的特性都是已经正式添加到该版本,并且已经过了预览阶段。
JAVA11新特性简单使用
1.String API
字符串可能是是日常开发中最常用的一个类,String类的方法使用频率也非常高。JAVA11新增了一系列实用的API
isBlank判空
1
2
3
4String s = " ";
boolean blank = s.isBlank();
//输出true
System.out.println(blank);lines()按行分割获取stream流
1
2
3
4
5
6
7String s2 = "第一行\n第二行\n第三行";
Stream<String> lines = s2.lines();
lines.forEach(System.out::println);
//输出
//第一行
//第二行
//第三行strip()去除空白字符。
trim
只能去除半角空格,而strip
是去除各种空白符1
2
3
4
5
6
7
8
9
10
11String s3 = " aaacccddd ";
//去除前后各种空白字符(包括全角半角)
System.out.println("==="+s3.strip()+"===");
//去除前面各种空白字符(包括全角半角)
System.out.println("==="+s3.stripLeading()+"===");
//去除后面各种空白字符(包括全角半角)
System.out.println("==="+s3.stripTrailing()+"===");
//输出
//===aaacccddd===
//===aaacccddd ===
//=== aaacccddd===repeat()复制字符串
1
2
3
4
5String s4 = "你好!";
String repeat = s4.repeat(4);
System.out.println(repeat);
//输出
//你好!你好!你好!你好!
2. 文件操作API
JAVA.nio.file.Files新增方法,读写文件更加简单
1 | //创建临时文件,写入内容 |
3. 更好用的Http Client API
从JAVA9的jdk.incubator.httpclient模块迁移到JAVA.net.http模块,包名由jdk.incubator.http改为JAVA.net.http。这是一个流畅、易于使用的API,完全支持HTTP/1.1和HTTP/2,可以同步或者异步处理响应。可以不需要再依赖第三方Http Client
1 | HttpClient client = HttpClient.newBuilder(). |
4.其他部分特性
局部变量类型推断。JAVA 11 支持在lambda表达式参数中使用局部变量语法(var关键字)。我们可以利用此特性将修饰符应用于局部变量
直接运行 JAVA 文件。省略JAVAc,直接通过命令执行.JAVA文件
推出的一款新的低延迟垃圾回收器 —— ZGC
新的实验性垃圾回收器 —Epsilon。Epsilon 垃圾回收器不执行任何垃圾回收工作,适用于模拟内存不足错误的场景。有一些特定的用例可能会有用:
- 性能测试
- 内存压力测试
- VM 接口测试
- 存活极短的任务
要启用它,添加
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
参数。飞行记录器(Flight Recorder)**飞行记录器 (JFR) 之前是 Oracle JDK 中的一个商用产品,现已在Open JDK中开源**。JFR 是一个性能分析工具,我们可以使用它从正在运行的 JAVA 应用程序中收集诊断和分析数据。要开启一个时长为 120 秒的 JFR 记录,我们可以使用以下参数:
1
-XX:StartFlightRecording=duration=120s,settings=profile,filename=JAVA-demo-app.jfr
JFR性能开销通常低于 1%,因此可以将它用于生产环境。记录的数据保存在.jfr文件中。为了分析和可视化数据,我们还需要使用另一款工具 —— JDK Mission Control (JMC) 。
还有一些重要的变化:
- 实现了新的 ChaCha20 和 ChaCha20-Poly1305 加密算法取代不安全的RC4。
- Support for cryptographic key agreement with Curve25519 and Curve448 replace the existing ECDH scheme
- 升级TLS版本到1.3,提升了安全性和性能
- 支持 Unicode 10, 带来了更多的字符、符号和表情符号
JAVA17新特性简单使用
注意,下边的新特性包含在12-17中预览并且发布的特性。
1 文本快
在支持文本块之前,相信都对Json等字符串转义、换行感到头疼,虽然大多数IDE支持复制后自动转义,不过大量的转义拼接导致可读性极差。
文本块在 JAVA 13 中预览发布,并正式添加到 JAVA 15 中,它可以简化多行字符串的写法,支持换行,并在不需要转义字符的情况下保持缩进。
1 | package com.test.JAVA17; |
2.增强Switch
switch表达式在新的版本中不断在增强功能,“万物皆可Switch“
1 | package com.test.JAVA17; |
相信绝大多数人都碰到过这种情况:忘记在 switch 里添加 break 语句,只有当代码在运行之后,并且发生错误之后才能发现。。。
switch 表达式通过一种有趣的方式修复了这个问题,只需要用逗号隔开同一个代码块里所有的值。不需要使用 break !它会替你处理好! 省略掉break,也让JAVA 语法更加简洁。
switch 表达式还新增了 yield 关键字。如果一个 case 进入了一个代码块,yield 将被作为 switch 表达式的返回语句。
1 | package com.test.JAVA17; |
3. 封印类
新增关键字sealed。sealed修饰的类和接口限制其他的类或者接口的扩展和实现。
1 | package com.test.JAVA17; |
4. record 类
record类在 JAVA 14 加入预览,并正式添加到 JAVA 16 中,替代传统的POJO 类。会自动实现equals()和 hashcode()方法会自动实现,toString()将返回这个类实例包含的所有字段的值。相对传统的POJO类的,让代码更加简洁。另外需要注意record 类是 final 和不可变的,属性也是final的。意味着类实例一旦被创建,它的字段就不能被修改。可以在 record 类中声明方法,包括非静态方法和静态方法
1 | package com.test.JAVA17; |
5. Instanceof模式匹配
模式匹配是 JAVA 消除冗长语法的路上的另一个举措。模式匹配在 JAVA 14加入预览,并正式添加到 JAVA 16 中,它可以在 instanceof 满足后省掉不必要的类型转换。
1 | package com.test.JAVA17; |
6. 优化的空指针异常可读性
优化空指针异常](https://openjdk.JAVA.net/jeps/358)在 JAVA 14 中正式发布,提高了空指针异常(NullPointerException,简称 NPE)的可读性,可以打印出在抛出异常位置所调用的方法的名称和空变量的名称。例如,如果你调用 a.b.getName(),而 b 为空,那么异常的堆栈跟踪信息会告诉你调用 getName()失败,因为 b 是空的。
1 | public static void main(String[] args) { |
7.增强的伪随机数生成器
增强的伪随机数生成器。将为伪随机数生成器 (PRNG) 提供新的接口类型和实现,包括可跳转的 PRNG 和额外的一类可拆分 PRNG 算法 (LXM)。新接口RandomGenerator将为所有现有的和新的 PRNG 提供统一的 API。将提供四个专门的 RandomGenerator 接口。推动该计划的重点是 JAVA 伪随机数生成领域的多个改进领域。这项工作不需要提供许多其他 PRNG 算法的实现。但是已经添加了一些常用算法,这些算法已经广泛部署在其他编程语言环境中。该计划的目标包括:
- 使在应用程序中交替使用各种 PRNG 算法变得更容易。
- 改进了对基于流的编程的支持,提供了 PRNG 对象流。
- 消除现有 PRNG 类中的代码重复。
- 保留类的现有行为JAVA.util.Random。
1 | package com.test.JAVA17; |
8.其它新特性
始终严格的浮点语义
在 JAVA SE 1.2 之前,所有的浮点计算都是严格的,但是以当初的情况来看,过于严格的浮点计算在当初流行的 x86 架构和 x87 浮点协议处理器上运行,需要大量的额外的指令开销,所以在 JAVA SE 1.2 开始,需要手动使用关键字 strictfp(strict float point) ,它可以用在类、接口或者方法上,被 strictfp 修饰的部分中的 float 和 double 表达式会进行严格浮点计算。但是随着时代发展,硬件早已发生巨变,当初的问题已经不存在了,所以从 JAVA 17 开始,删除了以前的默认语义,现在严格执行所有浮点操作。关键字strictfp仍然存在,但它没有效果。
JEP 410: Remove the Experimental AOT and JIT Compiler
删除实验性 AOT 和 JIT 编译器,它们几乎没有使用,但需要大量维护工作。该计划要求维护 JAVA 级别的 JVM 编译器接口,以便开发人员可以继续使用外部构建的编译器版本进行 JIT 编译。AOT 编译(jaotc 工具)作为一个实验性特性被整合到JDK 9中。该工具使用Graal 编译器,它本身是用 JAVA 编写的,用于 AOT 编译。这些实验性功能未包含在JDK 16 中由 Oracle 发布的版本,没有人抱怨。根据规定的计划,将删除三个 JDK 模块: jdk.aot(jaotc 工具);internal.vm.compiler,Graal 编译器;和 jdk.internal.vm.compiler.management,Graal MBean。与 AOT 编译相关的 HotSpot 代码也将被删除。
JEP 412: Foreign Function & Memory API (Incubator)
加入一个新的API,允许JAVA程序安全有效地访问JAVA堆之外的外部内存。连续在14,15,16预览,17种发布
与平台无关的矢量 API作为孵化 API集成到JDK 16中,将在 JDK 17 中再次孵化,提供一种机制来表达矢量计算,这些计算在运行时可靠地编译为支持的 CPU 架构上的最佳矢量指令。这比等效的标量计算获得了更好的性能。在 JDK 17 中,向量 API 已针对性能和实现进行了增强,包括在字节向量与布尔数组之间进行转换的增强功能。