JDK的第三個LTS版本JDK17來了

flydean發表於2021-11-15

簡介

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/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!

相關文章