Java 17 中有哪些新變化?
已發表: 2021-10-05Java 語言和運行時平台 Java 17 的長期支持 (LTS) 版本已於 2021 年 9 月 14 日推出。讓我們了解 Java 17 中的新增功能以及您是否應該升級。
許多應用程序使用舊版本的 Java,包括 Java 的早期 LTS 版本:Java 11 和 Java 8。
為什麼企業要升級到最新的 Java 版本? 升級到 Java 17 需要付出努力,主要是為了充分利用 JVM 內部的新特性和功能。
許多企業使用 Docker 和 Docker 鏡像以最少的精力和時間輕鬆切換到 Java 17。 開發人員可以定義他們的持續集成/部署 (CI/CD) 管道並在 Docker 映像中運行所有內容。 這不會影響使用舊 Java 版本的其他團隊,因為他們可以使用舊的 Docker 鏡像。
JAVA 17 特點
macOS 和 AArch64 支持
添加到此版本的關鍵 JVM 功能之一是使用 JEP 391 在 AArch64 架構上增強對 macOS 的支持。它將支持 Apple 去年隨其計算機發布的最新系列處理器 (M1)。
對於那些平台上的用戶來說,這不一定是什麼大問題,因為一些供應商已經推出了支持這種架構的 JDK 版本,甚至從 Java 8 中恢復支持。但是,官方批准印章對於確保未來的維護和支持至關重要該平台。 相比之下,Java 9 和 Windows/AArch64 在 Java 16 中添加了對 Linux/AArch64 平台的支持。
密封類
Sealed Classes 是 Java 17 中引入的一個特性。sealed Classes 特性已經完成了它的試用階段,並成為了 Java 17 中的官方平台和語言。它允許開發人員指定一個類型可以擁有的允許的子類型和防止他人以非預期的方式擴展或實施它。
當您嘗試將非密封類型轉換為不允許的子類型時,密封類還允許編譯器在編譯時生成錯誤。 Java 17 還為使用 Apple Metal API 而不是 OpenGL 在 macOS 上運行的 AWT/Swing 應用程序帶來了新的渲染管道。 它具有改進的 API 和增強的功能來生成隨機數。
Java 17 中的更改、刪除和限制
Java 17 還帶來了一些更改、刪除和新的限制。
JDK 內部的封裝
一個變化是JDK Internals的封裝過程結束。 這是第一次在 Java 9 中引入,當用戶嘗試使用反射或類似方法來規避使用內部 API 的通常限制時,它會在運行時發出警告。 還添加了命令行參數來規範這種行為。
從 Java 9 開始,已經創建了各種 API 來提供執行最常用任務的統一方法; 用戶將在內部使用這些 API。 在 Java 16 中,默認設置從警告更改為禁止訪問以引發異常。 但是,它使用命令行參數來改變行為。
在 Java 17 中,命令行參數被消除,並且可以取消此限制。 這意味著對這些內部 API 的所有非授權訪問現在都受到保護。
始終嚴格的浮點語義
額外的“移除”可以描述為重新引入 Always-Strict Floating Point 語義。 Java 1.2 引入了對 Java 中默認浮點語義的修改,允許 JVM 在浮點計算中犧牲少量精度以提高性能。 在必須使用嚴格語義的類和方法中,添加了strictfp關鍵字。 從那時起,CPU 中引入了各種指令集類型,從而可以在沒有不必要成本的情況下使用嚴格的浮點語義。 已經消除了實現默認或嚴格語義的需要。
Java 17 去掉了之前的默認語義,所有浮點運算都嚴格執行。 術語strictfp仍然存在。 但是,它不起作用並在編譯時導致警告。
提前 (AOT) 編譯
Java 9 引入了提前 (AOT) 編譯作為使用 Graal 編譯器的實驗性功能,並使用 Java 編寫了 JIT 代碼。 Java 10 通過合併 JVMCI 接口使 Graal 編譯器可用作 OpenJDK 中的 JIT 編譯器。 自從發布以來,它已經有了很大的改進。 Graal 編譯器取得了巨大的進步,其 JVM 以 GraalVM 的名義命名。
RMI 激活
JEP 407 從 Java 8 中刪除 RMI 激活後,它被取消,最終棄用並標記為在 Java 15 中刪除的要求。RMI 激活提供了一種方法,可以使用 RMI 啟用分佈式對象按需資源。 但是,它的使用很少,目前有更好的替代方案。 RMI 的其餘部分不受去除激活部分的影響。
小程序 API 刪除
Applet API 最終被 JEP 398 指定刪除,最初在 Java 9 中刪除。Applet API 提供了一種將 Java AWT/Swing 控件集成到瀏覽器中的網頁的方法。 但是,沒有現代瀏覽器可以支持這一點,這意味著在過去十年左右的時間裡,Applet 基本上無法訪問。

安全經理
最重要的棄用是它的安全管理器(JEP 411)。 從 Java 1.0 開始,安全管理器已經使用了一段時間。 它旨在限制 Java 可以在機器本地執行的操作,例如限制對網絡、文件和其他網絡資源的訪問。 它還嘗試通過阻止反射和特定 API 來沙箱化不受信任的代碼。
安全管理器的終結始於 Java 12。添加了命令行參數以阻止在運行時使用安全管理器。 Java 17 中所做的更改意味著嘗試從命令行或在運行時動態設置安全管理器時,JVM 中將生成運行時警告。
孵化器和預覽功能
考慮到 Java 17 被提升為長期支持的版本,許多人想知道 Java 17 是否會有任何預覽和孵化器功能。 Java 17 有兩個孵化器模塊和一個預覽功能!
矢量API
Vector API (JEP 414) 目前處於孵化器的第二階段。 API 允許開發人員定義向量計算,然後 JIT 編譯器將其轉換為 JVM 運行所在的 CPU 架構支持的適當向量指令(例如,使用 SSE 或 AVX 指令集的那些)。
以前,開發人員必須使用標量函數或構建特定於平台的本機庫。 在 Java 中實現 Vector API 還提供了一種在早期版本中很複雜的無縫回退機制。
Vector API 的標準化使 JDK 中的類能夠使用它。 Java Arrays mismatch() 方法可以更改為在 Java 上運行,從而無需在 JVM 中維護和編寫多個特定於平台的實現。
外部函數和內存 API
另一個孵化器功能稱為外來函數和內存 API (JEP 412)。 它是 Java 16 的另外兩個孵化器模塊的演變和合併,即外部鏈接器 API(JEP 389)和外部內存 API(JEP 393)。 它們都通過使用 Java 編寫的靜態類型編程提供對本機內存和代碼的訪問。
開關模式匹配
Java 17 中包含的語言預覽的最後一個功能是包含用於 Switch 的模式匹配 (JEP 406)。 此語言功能根據類型擴展了 switch 表達式和語句,類似於通過模式匹配 (JEP 394) 使用的語法,後者成為 Java 16 的標準。
過去,如果您想根據對象的動態特性執行不同的操作,則需要使用以下檢查實例構建 if-else 鏈:
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."; }; }您可能已經註意到,檢查過程中有一個變量的聲明。 與 Pattern 中的其他變量一樣,instance 的匹配表明此對像已進行類型檢查和強制轉換,並且可從其當前區域內的變量中獲得。
預覽功能是模式匹配的另一個步驟。 下一步是包括解構數組和記錄的能力。
你應該升級到 Java 17 嗎?
是的,您必須不斷升級到最新版本,但不能在第一天就升級。 您正在使用的軟件和庫可能尚未更新以兼容 Java 17,因此您可能需要等待一段時間才能完成。
如果您堅持使用 Java 8 或 Java 11 等 LTS 版本,則該語言和 JVM 本身有許多選項需要升級到 Java 17。由於它是一個長期維護版本,因此有您的生產環境最終也很有可能更新到 Java 17。
如果您正在開始一個全新的項目,或者正在讓您的項目為 Java 17 做好準備,那麼儘早切換到 Java 17 可能是最有效的選擇,因為它降低了遷移成本。 這也允許從事該項目的開發人員利用所有最新功能和運營方。
您可以利用過去幾年發生的許多改進,例如改進對在 Java 上運行的容器的支持,以及新的低延遲垃圾收集器實現。
