1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-16 18:10:13 +08:00

[feat] Java14新特性重构

This commit is contained in:
guide 2021-08-18 09:36:54 +08:00
parent e7e8d481d2
commit 801c2200fc

View File

@ -285,7 +285,7 @@ Optional.ofNullable(cache.getIfPresent(key))
为了最大限度地减少 Full GC 造成的应用停顿的影响,从 Java10 开始G1 的 FullGC 改为并行的标记清除算法,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量。 为了最大限度地减少 Full GC 造成的应用停顿的影响,从 Java10 开始G1 的 FullGC 改为并行的标记清除算法,同时会使用与年轻代回收和混合回收相同的并行工作线程数量,从而减少了 Full GC 的发生,以带来更好的性能提升、更大的吞吐量。
### 应用程序类数据共享(扩展CDS功能) ### 应用程序类数据共享(扩展 CDS 功能)
在 Java 5 中就已经引入了类数据共享机制 (Class Data Sharing简称 CDS),允许将一组类预处理为共享归档文件,以便在运行时能够进行内存映射以减少 Java 程序的启动时间,当多个 Java 虚拟机JVM共享相同的归档文件时还可以减少动态内存的占用量同时减少多个虚拟机在同一个物理或虚拟的机器上运行时的资源占用。CDS 在当时还是 Oracle JDK 的商业特性。 在 Java 5 中就已经引入了类数据共享机制 (Class Data Sharing简称 CDS),允许将一组类预处理为共享归档文件,以便在运行时能够进行内存映射以减少 Java 程序的启动时间,当多个 Java 虚拟机JVM共享相同的归档文件时还可以减少动态内存的占用量同时减少多个虚拟机在同一个物理或虚拟的机器上运行时的资源占用。CDS 在当时还是 Oracle JDK 的商业特性。
@ -513,7 +513,7 @@ Java12 为默认的垃圾收集器 G1 带来了两项更新:
传统的 `switch` 语法存在容易漏写 `break` 的问题,而且从代码整洁性层面来看,多个 break 本质也是一种重复 传统的 `switch` 语法存在容易漏写 `break` 的问题,而且从代码整洁性层面来看,多个 break 本质也是一种重复
Java12 提供`swtich` 表达式,使用类似 lambda 语法条件匹配成功后的执行块,不需要多写 break 。 Java12 增强`swtich` 表达式,使用类似 lambda 语法条件匹配成功后的执行块,不需要多写 break 。
```java ```java
switch (day) { switch (day) {
@ -553,30 +553,30 @@ if(obj instanceof String str){
#### 文本块 #### 文本块
解决 Java 定义多行字符串时只能通过换行转义或者换行连接符来变通支持的问题,引入**三重双引号**来定义多行文本 解决 Java 定义多行字符串时只能通过换行转义或者换行连接符来变通支持的问题,引入**三重双引号**来定义多行文本
两个`"""`中间的任何内容都会被解释为字符串的一部分,包括换行符。 Java 13 支持两个 `"""` 符号中间的任何内容都会被解释为字符串的一部分,包括换行符。
未支持文本块之前的 HTML 写法: 未支持文本块之前的 HTML 写法:
```java ```java
String json ="{\n" + String json ="{\n" +
" \"name\":\"mkyong\",\n" + " \"name\":\"mkyong\",\n" +
" \"age\":38\n" + " \"age\":38\n" +
"}\n"; "}\n";
``` ```
支持文本块之后的 HTML 写法: 支持文本块之后的 HTML 写法:
```java ```java
String json = """ String json = """
{ {
"name":"mkyong", "name":"mkyong",
"age":38 "age":38
} }
"""; """;
``` ```
未支持文本块之前的 SQL 写法: 未支持文本块之前的 SQL 写法:
@ -598,9 +598,9 @@ String query = """
另外,`String` 类新增加了 3 个新的方法来操作文本块: 另外,`String` 类新增加了 3 个新的方法来操作文本块:
- `formatted(Object... args)` :它类似于 `String`` format() `方法。添加它是为了支持文本块的格式设置。 - `formatted(Object... args)` :它类似于 `String``format()`方法。添加它是为了支持文本块的格式设置。
- `stripIndent()` :用于去除文本块中每一行开头和结尾的空格。 - `stripIndent()` :用于去除文本块中每一行开头和结尾的空格。
- `translateEscapes()` :转义序列如 *“\\\t”* 转换为 *“\t”* - `translateEscapes()` :转义序列如 _“\\\t”_ 转换为 _“\t”_
由于文本块是一项预览功能,可以在未来版本中删除,因此这些新方法被标记为弃用。 由于文本块是一项预览功能,可以在未来版本中删除,因此这些新方法被标记为弃用。
@ -610,14 +610,14 @@ public String stripIndent() {
} }
@Deprecated(forRemoval=true, since="13") @Deprecated(forRemoval=true, since="13")
public String formatted(Object... args) { public String formatted(Object... args) {
} }
@Deprecated(forRemoval=true, since="13") @Deprecated(forRemoval=true, since="13")
public String translateEscapes() { public String translateEscapes() {
} }
``` ```
#### Switch(引入 yield 关键字到 Switch 中) #### 增强 Switch(引入 yield 关键字到 Switch 中)
`Switch` 表达式中就多了一个关键字用于跳出 `Switch` 块的关键字 `yield`,主要用于返回一个值 `Switch` 表达式中就多了一个关键字用于跳出 `Switch` 块的关键字 `yield`,主要用于返回一个值
@ -645,7 +645,7 @@ ZGC 堆由一组称为 ZPages 的堆区域组成。在 GC 周期中清空 ZPages
Java Socket API 终于迎来了重大更新! Java Socket API 终于迎来了重大更新!
Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 ``PlainSocketImpl`` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`。 Java 13 将 Socket API 的底层进行了重写, `NioSocketImpl` 是对 `PlainSocketImpl` 的直接替代,它使用 `java.util.concurrent` 包下的锁而不是同步方法。如果要使用旧实现,请使用 `-Djdk.net.usePlainSocketImpl=true`
并且,在 Java 13 中是默认使用新的 Socket 实现,使其易于发现并在排除问题同时增加可维护性 并且,在 Java 13 中是默认使用新的 Socket 实现,使其易于发现并在排除问题同时增加可维护性
@ -675,120 +675,143 @@ $ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar
## Java14 ## Java14
### record 关键字
- 简化数据类的定义方式,使用 record 代替 class 定义的类,只需要声明属性,就可以在获得属性的访问方法,以及 toStringhashCode,equals 方法
- 类似于使用 Class 定义类,同时使用了 lomobok 插件,并打上了`@Getter,@ToString,@EqualsAndHashCode`注解
- 作为预览特性引入
```java
/**
* 这个类具有两个特征
* 1. 所有成员属性都是final
* 2. 全部方法由构造方法,和两个成员属性访问器组成(共三个)
* 那么这种类就很适合使用record来声明
*/
final class Rectangle implements Shape {
final double length;
final double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
double length() { return length; }
double width() { return width; }
}
/**
* 1. 使用record声明的类会自动拥有上面类中的三个方法
* 2. 在这基础上还附赠了equals()hashCode()方法以及toString()方法
* 3. toString方法中包括所有成员属性的字符串表示形式及其名称
*/
record Rectangle(float length, float width) { }
```
### 空指针异常精准提示 ### 空指针异常精准提示
- 通过 JVM 参数中添加`-XX:+ShowCodeDetailsInExceptionMessages`,可以在空指针异常中获取更为详细的调用信息,更快的定位和解决问题 通过 JVM 参数中添加`-XX:+ShowCodeDetailsInExceptionMessages`,可以在空指针异常中获取更为详细的调用信息,更快的定位和解决问题。
```java
a.b.c.i = 99; // 假设这段代码会发生空指针
```
```java
Exception in thread "main" java.lang.NullPointerException:
Cannot read field 'c' because 'a.b' is null.
at Prog.main(Prog.java:5) // 增加参数后提示的异常中很明确的告知了哪里为空导致
```
### switch 的增强终于转正
- JDK12 引入的 switch预览特性在 JDK14 变为正式版本,不需要增加参数来启用,直接在 JDK14 中就能使用
- 主要是用`->`来替代以前的`:`+`break`;另外就是提供了 yield 来在 block 中返回值
_Before Java 14_
```java ```java
switch (day) { a.b.c.i = 99; // 假设这段代码会发生空指针
case MONDAY:
case FRIDAY:
case SUNDAY:
System.out.println(6);
break;
case TUESDAY:
System.out.println(7);
break;
case THURSDAY:
case SATURDAY:
System.out.println(8);
break;
case WEDNESDAY:
System.out.println(9);
break;
}
``` ```
_Java 14 enhancements_ Java 14 之前:
```java ```java
switch (day) { Exception in thread "main" java.lang.NullPointerException
case MONDAY, FRIDAY, SUNDAY -> System.out.println(6); at NullPointerExample.main(NullPointerExample.java:5)
case TUESDAY -> System.out.println(7);
case THURSDAY, SATURDAY -> System.out.println(8);
case WEDNESDAY -> System.out.println(9);
}
``` ```
### instanceof 增强 Java 14 之后:
```java
// 增加参数后提示的异常中很明确的告知了哪里为空导致
Exception in thread "main" java.lang.NullPointerException:
Cannot read field 'c' because 'a.b' is null.
at Prog.main(Prog.java:5)
```
### switch 的增强(转正)
Java12 引入的 switch预览特性在 Java14 变为正式版本,不需要增加参数来启用,直接在 JDK14 中就能使用。
Java12 为 switch 表达式引入了类似 lambda 语法条件匹配成功后的执行块,不需要多写 break Java13 提供了 `yield` 来在 block 中返回值。
```java
String result = switch (day) {
case "M", "W", "F" -> "MWF";
case "T", "TH", "S" -> "TTS";
default -> {
if(day.isEmpty())
yield "Please insert a valid day.";
else
yield "Looks like a Sunday.";
}
};
System.out.println(result);
```
### 预览新特性
#### record 关键字
简化数据类的定义方式,使用 `record` 代替 `class` 定义的类,只需要声明属性,就可以在获得属性的访问方法,以及 `toString()``hashCode()`, `equals()`方法
类似于使用 `class` 定义类,同时使用了 lomobok 插件,并打上了`@Getter,@ToString,@EqualsAndHashCode`注解
```java
/**
* 这个类具有两个特征
* 1. 所有成员属性都是final
* 2. 全部方法由构造方法,和两个成员属性访问器组成(共三个)
* 那么这种类就很适合使用record来声明
*/
final class Rectangle implements Shape {
final double length;
final double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
double length() { return length; }
double width() { return width; }
}
/**
* 1. 使用record声明的类会自动拥有上面类中的三个方法
* 2. 在这基础上还附赠了equals()hashCode()方法以及toString()方法
* 3. toString方法中包括所有成员属性的字符串表示形式及其名称
*/
record Rectangle(float length, float width) { }
```
#### 文本块
Java14 中,文本块依然是预览特性,不过,其引入了两个新的转义字符:
- `\` : 表示行尾,不引入换行符
- `\s` :表示单个空格
```java
String str = "凡心所向,素履所往,生如逆旅,一苇以航。";
String str2 = """
凡心所向,素履所往, \
生如逆旅,一苇以航。""";
System.out.println(str2);// 凡心所向,素履所往, 生如逆旅,一苇以航。
String text = """
java
c++\sphp
""";
System.out.println(text);
//输出:
java
c++ php
```
#### instanceof 增强
依然是**预览特性** Java 12 新特性中介绍过。 依然是**预览特性** Java 12 新特性中介绍过。
### 其他特性 ### Java14 其他特性
- 从 Java11 引入的 ZGC 作为继 G1 过后的下一代 GC 算法,从支持 Linux 平台到 Java14 开始支持 MacOS 和 Window个人感觉是终于可以在日常开发工具中先体验下 ZGC 的效果了,虽然其实 G1 也够用) - 从 Java11 引入的 ZGC 作为继 G1 过后的下一代 GC 算法,从支持 Linux 平台到 Java14 开始支持 MacOS 和 Window个人感觉是终于可以在日常开发工具中先体验下 ZGC 的效果了,虽然其实 G1 也够用)
- 移除了 CMS 垃圾收集器(功成而退) - 移除了 CMS(Concurrent Mark Sweep) 垃圾收集器(功成而退)
- 新增了 jpackage 工具,标配将应用打成 jar 包外,还支持不同平台的特性包,比如 linux 下的`deb``rpm`window 平台下的`msi``exe` - 新增了 jpackage 工具,标配将应用打成 jar 包外,还支持不同平台的特性包,比如 linux 下的`deb``rpm`window 平台下的`msi``exe`
## 总结 ## 总结
### 关于预览特性 ### 关于预览特性
- 先贴一段 oracle 官网原文:`This is a preview feature, which is a feature whose design, specification, and implementation are complete, but is not permanent, which means that the feature may exist in a different form or not at all in future JDK releases. To compile and run code that contains preview features, you must specify additional command-line options.` 先贴一段 oracle 官网原文:`This is a preview feature, which is a feature whose design, specification, and implementation are complete, but is not permanent, which means that the feature may exist in a different form or not at all in future JDK releases. To compile and run code that contains preview features, you must specify additional command-line options.`
- 这是一个预览功能,该功能的设计,规格和实现是完整的,但不是永久性的,这意味着该功能可能以其他形式存在或在将来的 JDK 版本中根本不存在。 要编译和运行包含预览功能的代码,必须指定其他命令行选项。
- 就以`switch`的增强为例子,从 Java12 中推出,到 Java13 中将继续增强,直到 Java14 才正式转正进入 JDK 可以放心使用,不用考虑后续 JDK 版本对其的改动或修改 这是一个预览功能,该功能的设计,规格和实现是完整的,但不是永久性的,这意味着该功能可能以其他形式存在或在将来的 JDK 版本中根本不存在。 要编译和运行包含预览功能的代码,必须指定其他命令行选项。
- 一方面可以看出 JDK 作为标准平台在增加新特性的严谨态度,另一方面个人认为是对于预览特性应该采取审慎使用的态度。特性的设计和实现容易,但是其实际价值依然需要在使用中去验证
就以`switch`的增强为例子,从 Java12 中推出,到 Java13 中将继续增强,直到 Java14 才正式转正进入 JDK 可以放心使用,不用考虑后续 JDK 版本对其的改动或修改
一方面可以看出 JDK 作为标准平台在增加新特性的严谨态度,另一方面个人认为是对于预览特性应该采取审慎使用的态度。特性的设计和实现容易,但是其实际价值依然需要在使用中去验证
### JVM 虚拟机优化 ### JVM 虚拟机优化
- 每次 Java 版本的发布都伴随着对 JVM 虚拟机的优化,包括对现有垃圾回收算法的改进,引入新的垃圾回收算法,移除老旧的不再适用于今天的垃圾回收算法等 每次 Java 版本的发布都伴随着对 JVM 虚拟机的优化,包括对现有垃圾回收算法的改进,引入新的垃圾回收算法,移除老旧的不再适用于今天的垃圾回收算法等
- 整体优化的方向是**高效,低时延的垃圾回收表现**
- 对于日常的应用开发者可能比较关注新的语法特性,但是从一个公司角度来说,在考虑是否升级 Java 平台时更加考虑的是**JVM 运行时的提升**
## 参考信息 整体优化的方向是**高效,低时延的垃圾回收表现**
对于日常的应用开发者可能比较关注新的语法特性,但是从一个公司角度来说,在考虑是否升级 Java 平台时更加考虑的是**JVM 运行时的提升**
## 参考资料
- JDK Project Overview <https://openjdk.java.net/projects/jdk/ >
- IBM Developer Java9 <https://www.ibm.com/developerworks/cn/java/the-new-features-of-Java-9/> - IBM Developer Java9 <https://www.ibm.com/developerworks/cn/java/the-new-features-of-Java-9/>
- Guide to Java10 <https://www.baeldung.com/java-10-overview> - Guide to Java10 <https://www.baeldung.com/java-10-overview>
- Java 10 新特性介绍<https://www.ibm.com/developerworks/cn/java/the-new-features-of-Java-10/index.html> - Java 10 新特性介绍<https://www.ibm.com/developerworks/cn/java/the-new-features-of-Java-10/index.html>
@ -800,4 +823,5 @@ switch (day) {
- New Java13 Features <https://www.baeldung.com/java-13-new-features> - New Java13 Features <https://www.baeldung.com/java-13-new-features>
- Java13 新特性概述 <https://www.ibm.com/developerworks/cn/java/the-new-features-of-Java-13/index.html> - Java13 新特性概述 <https://www.ibm.com/developerworks/cn/java/the-new-features-of-Java-13/index.html>
- Oracle Java14 record <https://docs.oracle.com/en/java/javase/14/language/records.html> - Oracle Java14 record <https://docs.oracle.com/en/java/javase/14/language/records.html>
- java14-features <https://www.techgeeknext.com/java/java14-features> - java14-features <https://www.techgeeknext.com/java/java14-features>
- Java 14 Features : <https://www.journaldev.com/37273/java-14-features>