JavaGuide/docs/java/new-features/java14-15.md

244 lines
7.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: Java 14 & 15 新特性概览
category: Java
tag:
- Java新特性
---
## Java14
### 空指针异常精准提示
通过 JVM 参数中添加`-XX:+ShowCodeDetailsInExceptionMessages`,可以在空指针异常中获取更为详细的调用信息,更快的定位和解决问题。
```java
a.b.c.i = 99; // 假设这段代码会发生空指针
```
Java 14 之前:
```java
Exception in thread "main" java.lang.NullPointerException
at NullPointerExample.main(NullPointerExample.java:5)
```
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` 关键字可以简化 **数据类**(一个 Java 类一旦实例化就不能再修改)的定义方式,使用 `record` 代替 `class` 定义的类,只需要声明属性,就可以在获得属性的访问方法,以及 `toString()``hashCode()`, `equals()`方法。
类似于使用 `class` 定义类,同时使用了 lombok 插件,并打上了`@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 新特性](./java12-13.md)中介绍过。
### 其他
- 从 Java11 引入的 ZGC 作为继 G1 过后的下一代 GC 算法,从支持 Linux 平台到 Java14 开始支持 MacOS 和 Windows个人感觉是终于可以在日常开发工具中先体验下 ZGC 的效果了,虽然其实 G1 也够用)
- 移除了 CMS(Concurrent Mark Sweep) 垃圾收集器(功成而退)
- 新增了 jpackage 工具,标配将应用打成 jar 包外,还支持不同平台的特性包,比如 linux 下的`deb`和`rpm`window 平台下的`msi`和`exe`
## Java15
### CharSequence
`CharSequence` 接口添加了一个默认方法 `isEmpty()` 来判断字符序列为空,如果是则返回 true。
```java
public interface CharSequence {
default boolean isEmpty() {
return this.length() == 0;
}
}
```
### TreeMap
`TreeMap` 新引入了下面这些方法:
- `putIfAbsent()`
- `computeIfAbsent()`
- `computeIfPresent()`
- `compute()`
- `merge()`
### ZGC(转正)
Java11 的时候 ZGC 还在试验阶段。
当时ZGC 的出现让众多 Java 开发者看到了垃圾回收器的另外一种可能,因此备受关注。
经过多个版本的迭代不断的完善和修复问题ZGC 在 Java 15 已经可以正式使用了!
不过,默认的垃圾回收器依然是 G1。你可以通过下面的参数启动 ZGC
```bash
java -XX:+UseZGC className
```
### EdDSA(数字签名算法)
新加入了一个安全性和性能都更强的基于 Edwards-Curve Digital Signature Algorithm EdDSA实现的数字签名算法。
虽然其性能优于现有的 ECDSA 实现,不过,它并不会完全取代 JDK 中现有的椭圆曲线数字签名算法( ECDSA)。
```java
KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519");
KeyPair kp = kpg.generateKeyPair();
byte[] msg = "test_string".getBytes(StandardCharsets.UTF_8);
Signature sig = Signature.getInstance("Ed25519");
sig.initSign(kp.getPrivate());
sig.update(msg);
byte[] s = sig.sign();
String encodedString = Base64.getEncoder().encodeToString(s);
System.out.println(encodedString);
```
输出:
```plain
0Hc0lxxASZNvS52WsvnncJOH/mlFhnA8Tc6D/k5DtAX5BSsNVjtPF4R4+yMWXVjrvB2mxVXmChIbki6goFBgAg==
```
### 文本块(转正)
在 Java 15 ,文本块是正式的功能特性了。
### 隐藏类(Hidden Classes)
隐藏类是为框架frameworks所设计的隐藏类不能直接被其他类的字节码使用只能在运行时生成类并通过反射间接使用它们。
### 预览新特性
#### 密封类
**密封类Sealed Classes** 是 Java 15 中的一个预览新特性。
没有密封类之前,在 Java 中如果想让一个类不能被继承和修改,我们可以使用`final` 关键字对类进行修饰。不过,这种方式不太灵活,直接把一个类的继承和修改渠道给堵死了。
密封类可以对继承或者实现它们的类进行限制,这样这个类就只能被指定的类继承。
```java
// 抽象类 Person 只允许 Employee 和 Manager 继承。
public abstract sealed class Person
permits Employee, Manager {
//...
}
```
另外,任何扩展密封类的类本身都必须声明为 `sealed`、`non-sealed` 或 `final`
```java
public final class Employee extends Person {
}
public non-sealed class Manager extends Person {
}
```
![](https://oss.javaguide.cn/javaguide/image-20210820153955587.png)
如果允许扩展的子类和封闭类在同一个源代码文件里,封闭类可以不使用 permits 语句Java 编译器将检索源文件,在编译期为封闭类添加上许可的子类。
#### instanceof 模式匹配
Java 15 并没有对此特性进行调整,继续预览特性,主要用于接受更多的使用反馈。
在未来的 Java 版本中Java 的目标是继续完善 `instanceof` 模式匹配新特性。
### 其他
- **Nashorn JavaScript 引擎彻底移除**Nashorn 从 Java8 开始引入的 JavaScript 引擎Java9 对 Nashorn 做了些增强,实现了一些 ES6 的新特性。在 Java 11 中就已经被弃用,到了 Java 15 就彻底被删除了。
- **DatagramSocket API 重构**
- **禁用和废弃偏向锁Biased Locking**:偏向锁的引入增加了 JVM 的复杂性大于其带来的性能提升。不过,你仍然可以使用 `-XX:+UseBiasedLocking` 启用偏向锁定,但它会提示这是一个已弃用的 API。
- ……
<!-- @include: @article-footer.snippet.md -->