簡介
2021年9月JDK17釋出了,JDK17是最新的一個LTS版本。所謂LTS版本就是可以得到至少八年產品支援的版本。從2014年的JDK8,到2018年的JDK11,再到2021年的JDK17。
同時Oracle也調整了LTS版本的釋出年限,從之前的三年調整到現在的二年,也就是說下一個LTS版本將會是JDK21,哇喔!
那麼如果不是LTS版本呢? 非LTS版本只會得到六個月的產品支援。所以大家還是使用LTS版本吧。
好了,讓我們一起來看看JDK17中都有那些新特性吧。
JDK17中的新特性
總中的來說,JDK17提供了14個優化點或者是變動點。我們會一一進行講解。
語言上的新特性
JDK17在語言上的新特性只有一個 JEP 409: Sealed Classes。
Sealed Classes是在JDK15中引入的概念,它表示某個類允許哪些類來繼承它:
public sealed class SealExample permits Seal1, Seal2{
}
public non-sealed class Seal1 extends SealExample {
}
public final class Seal2 extends SealExample {
}
final表示Seal2不能再被繼承了。non-sealed 表示可以允許任何類繼承。
核心庫的優化
JDK17對JAVA核心庫的優化有4個。
- 第一個是:JEP 306: Restore Always-Strict Floating-Point Semantics
這個是什麼呢?簡單點說,就是之前的硬體架構,在嚴格進行浮點語義進行計算的時候,會消耗大量資源。這在很久以前硬體水平都不高的時候,是難以容忍的。
所以在JDK1.2之後,對浮點語義進行了微調,對預設的嚴格浮點語義進行了修改。
但是現在已經是2021年了,硬體水平得到了飛速的發展,所以之前引入的修改已經是不必要了,在JDK17中被廢棄了。
- 第二個是:JEP 356: Enhanced Pseudo-Random Number Generator
JDK中有一個專門生成隨機數的類java.util.Random,但是這個類生成的都是偽隨機數。
JDK17對這個類進行了加強,提供了一個RandomGenerator介面,為所有的偽隨機數提供統一的API。
RandomGenerators 提供了ints、longs、doubles、nextBoolean、nextInt、nextLong、nextDouble 和 nextFloat等方法,來生成對應的隨機數。
RandomGenerator介面又包括4個子介面,分別是:
SplittableRandomGenerator:提供了 split 和 splits 的方法,允許使用者從現有的 RandomGenerator 生成一個新的 RandomGenerator.
JumpableRandomGenerator:擴充套件了RandomGenerator的jump 和 jumps 的方法,允許使用者跳過一定數目的隨機數。
LeapableRandomGenerator :擴充套件了RandomGenerator的leap 和leaps 的方法,允許使用者跳過大量數目的隨機數。
ArbitrouslyJumpableRandomGenerator:擴充套件了LeapableRandomGenerator,允許使用者指定跳過的隨機數。
同時還對Random、ThreadLocalRandom 和 SplittableRandom等類進行了重構。
- 第三個是JEP 382: New macOS Rendering Pipeline
這個是專門為Mac做的優化,使用了最新的Apple Metal API 來實現JAVA的2D渲染。
- 第四個是JEP 415: Context-Specific Deserialization Filters
JDK中一個很危險的用法就是反序列化,因為你不知道反序列化的物件到底是不是一個危險的物件,為了解決這個問題,在Java 9 中引入了反序列化過濾器,從而在反序列化之前對資料流進行驗證。
但是這種基於流的過濾器有幾個限制,這種方法不能擴充套件,並且很難在程式碼釋出後更新過濾器。它也不能對應用程式中第三方庫執行的反序列化操作進行過濾。
為了解決這些問題,JEP 290 還引入了一個 JVM 範圍的反序列化過濾器,可以通過 API、系統屬性或安全屬性進行設定。但是這種靜態的過濾器,在具有多個執行上下文的複雜應用程式中,往往會不太適用,因為不同的上下文可能需要不同的過濾條件。
JDK17對JDK9的過濾方法進行了改進,可以在JVM範圍配置特定於上下文的反序列化過濾器。
支援新的平臺
- JEP 391: macOS AArch 64 Port
Mac的M1晶片都發布好久了,沒有理由JDK不支援,這個JEP就是讓JDK17支援原生的Apple的新Arm 64架構。
預覽特性
- JEP 406: Pattern Matching for switch (Preview)
這個新特性允許在switch中使用模式匹配。
我們知道,在之前的預覽功能中,已經有模式匹配了,不過模式匹配是用在instance of語句中,如下所示:
// Old code
if (o instanceof String) {
String s = (String)o;
... use s ...
}
// New code
if (o instanceof String s) {
... use s ...
}
但是如果instanceof太多的話,也會造成困擾:
static String formatter(Object o) {
String formatted = "unknown";
if (o instanceof Integer i) {
formatted = String.format("int %d", i);
} else if (o instanceof Long l) {
formatted = String.format("long %d", l);
} else if (o instanceof Double d) {
formatted = String.format("double %f", d);
} else if (o instanceof String s) {
formatted = String.format("String %s", s);
}
return formatted;
}
最好的辦法是將上面的程式碼轉換成為switch:
static String formatterPatternSwitch(Object o) {
return switch (o) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
default -> o.toString();
};
}
這就是switch中的模式匹配。
- JEP 412: Foreign Function and Memory API (Incubator)
在JDK14和15中,JDK已經可以呼叫不屬於JVM內部的程式碼和訪問不歸JVM管轄的記憶體空間。這個新特性在JDK17中得到了增強。
想象一下,以後JDK可以原生支援呼叫非java語言的API,是不是很厲害?
- JEP 414: Vector API (Second Incubator)
Vector是在JDK16中引入的。可以讓向量計算更加快速。 迴圈遍歷的計算,可以用Vector來進行簡化。
其他改動
其他的一些改動比如封裝JDK內部使用的API ,廢棄了Security Manager,Applet API和RMI等等,這裡就不一一介紹了。
總結
JDK17是一個LTS版本,也提供了很多優秀的新特性,還不趕緊用起來!
本文已收錄於 http://www.flydean.com/27-jdk17-new-features/
最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!
歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!