天天看點

#yyds幹貨盤點#JDK的第三個LTS版本JDK17來了

文章目錄

  • ​​簡介​​
  • ​​JDK17中的新特性​​
  • ​​語言上的新特性​​
  • ​​核心庫的優化​​
  • ​​支援新的平台​​
  • ​​預覽特性​​
  • ​​其他改動​​
  • ​​總結​​

簡介

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等等,這裡就不一一介紹了。

總結