Java 17新特性

banq發表於2021-09-08

Java 17計劃於 9 月 14日釋出,來自不同供應商的版本將在當天或之後釋出。Java 17 的特別之處當然是 Oracle 和 OpenJDK 社群都決定這將是一個長期支援版本,就像 Java 11 和之前的 Java 8 一樣。
自從從 Java 10 開始引入快速釋出節奏以來,除 Oracle 之外的許多供應商都加緊生產具有各種級別支援的生產就緒二進位制檔案,包括AmazonAzulBellSoftMicrosoftSAPEclipse Adoptium(以前為AdoptOpenJDK)。
 
下面是新的特性:
  • macOS 上的 AArch64 支援

此版本中新增的突出功能之一是支援AArch64上的macOS ,增加了Apple 去年釋出的新 CPU 系列 (M1) 的支援。對於在這些平臺上執行的人來說,這並不是什麼新聞,因為一些供應商已經發布了支援這種架構的 JDK 版本,甚至將支援一直回溯到 Java 8。 儘管如此,官方批准版本仍然很重要平臺未來的維護和支援。為了比較,Java 9 中新增了對 Linux/AArch64 平臺的支援,Java 16 中新增了對 Windows/AArch64 的支援。
  • 密封類

Sealed Classes 特性已完成其預覽階段,現在是 Java 17 中語言和平臺的標準部分,如JEP 409 中所定義。密封類允許開發人員顯式宣告型別的允許子型別,從而防止其他人無意中擴充套件或實現它。
  • 其他新功能

Java 17 還為在 macOS 上執行的 AWT/Swing 應用程式帶來了新的渲染管道 ( JEP 382 ),使用 Apple 的 Metal API 而不是 OpenGL,以及用於生成隨機數的新 API 和增強功能 ( JEP 356 )。
  
其他限制或棄用功能:
  • JDK內部元素強封裝

JEP 403強封裝 JDK 的所有內部元素,除了 關鍵的內部 API,如sun.misc.Unsafe. 不再可能透過單個命令列選項訪問。將 JDK 從預設的寬鬆強封裝轉換為預設 強封裝。
在Java9中,如果使用者嘗試使用反射或喜歡繞過使用其他內部 API 的正常限制,則會發出執行時警告。還新增了命令列引數來控制此行為。在 Java 16 中,預設設定從發出警告更改為透過丟擲異常拒絕訪問,但仍保留命令列引數以更改行為。
現在在 Java 17 中,進一步刪除了這些命令列引數,當然也能禁用此限制,這意味著對這些內部 API 的所有未經授權的訪問現在都被強封裝。
好處:

  1. 繼續提高 JDK 的安全性和可維護性
  2. 鼓勵開發人員從使用內部元素遷移到使用標準 API,以便他們和他們的使用者可以輕鬆升級到未來的 Java 版本。

 
  • 始終嚴格的浮點語義

恢復 Always-Strict Floating-Point Semantics ( JEP 306 )。Java 1.2 引入了對 Java 中預設浮點語義的更改,實質上允許 JVM 以犧牲一點點浮點精度來換取效能。對於需要應用嚴格語義的方法和類,引入了一個關鍵字strictfp。從那時起,新的指令集被新增到 CPU 中,導致在沒有過度開銷的情況下操作嚴格的浮點語義,因此不再有預設和嚴格語義的動機。
Java 17 刪除了以前的預設語義,所有浮點運算現在都嚴格執行。該關鍵字strictfp仍然存在,但沒有效果併產生編譯時警告。
 
  • 刪除實驗性 AOT 和 JIT 編譯器

刪除實驗性的基於 Java 的提前 (AOT) 和即時 (JIT) 編譯器。該編譯器自推出以來幾乎沒有什麼用處,維護它所需的工作量很大。
Java 9 引入了提前 (AOT) 編譯作為使用 Graal 編譯器(一種用 Java 編寫的 JIT 編譯器)的實驗性功能。Java 10 使用新增的 JVMCI 介面使 Graal 編譯器可用作 OpenJDK 中的 JIT 編譯器。
JEP 410 中,AOT 和 JIT 編譯器已被刪除。
  • 刪除RMI 啟用

RMI Activation 在JEP 407 中被刪除,在 Java 8 中成為可選的,最終在 Java 15 中被棄用並標記為刪除。 RMI Activation 啟用了一種透過 RMI 啟用分散式物件按需資源的方法,但幾乎沒有用,並且今天存在更好的替代方案。RMI 的其餘部分不受啟用部分的影響。
  • 刪除Applet API

Applet API 終於在JEP 398 中被標記為刪除,它之前在 Java 9 中被棄用。 Applet API 提供了一種將 Java AWT/Swing 控制元件嵌入到瀏覽器網頁中的方法,但今天沒有現代瀏覽器支援這一點,所以在過去十年或更長時間裡,Applet 基本上是無關緊要的。
  • 棄用安全管理器

毫無疑問,最大的棄用是安全管理器(JEP 411)。安全管理器自 Java 1.0 以來一直存在,通常旨在限制 Java 可以在本地機器上執行的操作,例如限制對檔案、網路等的訪問,或透過禁止使用反射來嘗試沙箱不可信程式碼,以及某些 API。
安全管理器的棄用始於 Java 12,其中新增了一個禁止使用它的命令列引數,從 Java 18 開始,該命令列引數將預設為禁止在執行時設定安全管理器。Java 17 中的更改意味著在嘗試從命令列或在執行時動態設定安全管理器時,JVM 將產生執行時警告。
 

孵化器和預覽功能
許多人想知道 Java 17 是否會有任何孵化器和預覽功能,因為它被提升為一個長期支援的版本,並且可能支援一個改變或長時間沒有被淘汰的功能似乎是不明智的。但是我們來了,Java 17 有兩個孵化器模組和一個預覽語言功能!

  • Vector API 

Vector API ( JEP 414 ) 正在經歷其第二個孵化器階段。該 API 使開發人員能夠表達向量計算,然後 JIT 編譯器可以將其編譯為執行 JVM 的 CPU 架構所支援的適當向量指令(例如,利用 SSE 和 AVX 指令集)。
以前,開發人員要麼必須依賴標量操作,要麼必須使用/開發特定於平臺的本機庫。在 Java 中實現 Vector API 還可以為當前架構沒有必要指令的事物提供優雅的回退,而是必須回退以以不同的方式計算。
雖然不是此 JEP 的一部分,但 Vector API 的標準化也使 JDK 中的類能夠使用它。諸如 Arrays.mismatch 之類的方法,如今在某些平臺上具有固有的向量化實現,可以重寫以使其全部在 Java 中執行,從而無需在 JVM 中編寫和維護多個特定於平臺的實現。
  • 外部函式和記憶體 API

另一個孵化器模組是外來函式和記憶體 API ( JEP 412 ),它在技術上是 Java 16 中兩個先前孵化器模組的合併和演變:外來連結器 API ( JEP 389 ) 和外來記憶體訪問 API ( JEP 393 )。這兩個組合允許使用用 Java 編寫的靜態型別程式碼訪問本機程式碼和記憶體的方法,目的是能夠在這種情況下取​​代 JNI 的使用。
  • Switch模式匹配

Java 17 中的最後一個語言預覽功能是包含用於 switch 的模式匹配 ( JEP 406 )。此語言功能擴充套件了 switch 表示式和語句,使其還能夠基於型別進行 switch,類似於模式匹配引入的 instanceof ( JEP 394 )語法,該語法在 Java 16 中標準化。
以前,如果您想根據物件的動態型別執行不同的操作,您需要使用 instanceof 檢查建立一個 if-else if 鏈,例如:

String type(Object o) {
  if (o instanceof List) {
    return "A List of things.";
  }
  else if (o instanceof Map) {
    return "A Map! It has keys and values.";
  }
  else if (o instanceof String) {
    return "This is a string.";
  }
  else {
    return "This is something else.";
  }
}

結合使用 switch 表示式和 switch 的新模式匹配,它可以簡化為:

String type(Object o) {
  return switch (o) {
    case List l -> "A List of things.";
    case Map m -> "A Map! It has keys and values.";
    case String s -> "This is a string.";
    default -> "This is something else.";
  };
}



 

相關文章