各位 Java 開發者,你們準備好迎接 Java 24 到來了嗎!XD
作為 2025 年第一個主要版本更新,Java 24 預計將於 2025 年 3 月 18 日正式發布,並帶來一系列令人期待的新功能和改進。除了上一版中重要的預覽特性會轉為正式功能之外,它還包含了多項全新功能,以及若干實驗性的改進。
本文將簡介 Java 24 中的 24 項 JEP(JDK Enhancement Proposals)。它們涵蓋了垃圾收集器優化、安全性增強、程式設計範式的改進,以及重要的 API 更新,這些功能將為 Java 開發者帶來更好的開發體驗和更強大的功能支持。
目錄
前言
Java 24 是目前 Java SE 平台的最新版本,尚處於初始候選版本階段,並預計於今年三月正式發布。
目前的初始候選版本中包含許多新功能,例如在效能優化方面引入了實驗性的分代 Shenandoah 垃圾收集器(JEP 404)和壓縮物件標頭(JEP 450)功能,同時也改進了 G1 收集器的屏障擴展機制(JEP 475)。這些改進將為 Java 應用程式提供更好的記憶體管理效能。
在安全性方面新增了量子電腦防禦機制,包括基於模格的金鑰封裝機制(JEP 496)和數位簽章演算法(JEP 497)。同時,本版也永久停用了安全管理器(JEP 486),並開始為限制 JNI 使用做出準備(JEP 472)。
在開發工具和函式庫方面,Java 24 將類別檔案 API(JEP 484)和串流聚集器(JEP 485)從預覽轉為正式功能。此外,還引入了預先類別的載入和連結功能(JEP 483),以及不需要 JMOD 檔案的執行時映像連結功能(JEP 493)。
值得注意的是,Java 24 也包含了多個繼續維持預覽階段的功能,如範圍值、模式的基礎型別匹配、向量 API 等,它們會在之後的版本中進一步完善。
時程表
以下是預定的時程表:
- 2024 年 12 月 5 日:第一階段降溫(功能凍結加入並僅能移除、穩定性測試)
- 2025 年 1 月 16 日:第二階段降溫(更嚴格的錯誤修復條件、測試與優化)
- 2025 年 2 月 6 日:初始候選版本(完成新功能整合到主線、重點測試與修復)
- 2025 年 2 月 20 日:最終候選版本
- 2025 年 3 月 18 日:正式發布
之後老喬會開始逐篇完整介紹 Java 24 中的全新正式功能,以及從預覽階段轉為正式的特性。對於本版中的預覽功能和移除公告,則會採用快速導覽的方式去簡介幾個較重要的改進,就不會大篇幅的說明了。
語言改進
JEP 488:模式、instanceof 與 switch 中的基礎型別匹配(第二次預覽)
- 本站介紹:JDK 23 功能預覽:JEP 455 基礎型別的模式匹配(規格未變更故延用前版簡介)
- 官方介紹:Primitive Types in Patterns, instanceof, and switch (Second Preview)
本功能解除了基礎型別在模式匹配中存在的幾個限制。處理基礎型別和物件型別的程式碼將會被簡化,不再需要特殊處理,使得這兩種型別可以用相同的方式應對。由於現在可以自動處理條件式轉型(值必須被檢查以確保它對目標型別有效),因此允許 instanceof
接受基礎型別的話可以進一步減少程式碼數量。
它增強了 Java 的模式匹配功能,並擴展 instanceof
和 switch
,使其能夠在所有模式的上下文中使用基礎型別的模式匹配:
- 基礎型別模式的增強:允許在模式匹配中適用更廣泛的候選基礎型別,例如
record Test(double d)
可以使用x instanceof Test(int i)
去判定d
值是否能轉型成int
instanceof
的擴展:允許instanceof
運算符與基礎型別一起使用,例如if (x instanceof int i) { ... }
switch
的擴展:允許switch
表達式處理所有基礎型別,包括boolean
、float
、double
和long
,例如case byte b -> ...
JEP 494:模組匯入宣告(第二次預覽)
- 本站介紹:待補充額外增加的新特性介紹、JDK 23 功能:JEP 476 模組化的匯入聲明(前版預覽介紹)
- 官方介紹:Module Import Declarations (Second Preview)
它允許開發者透過單一陳述句去匯入模組中的所有公開型別,以簡化模組化函式庫的重複使用。有了這項功能,初學者便能更輕鬆地使用第三方函式庫和基礎 Java 類別,而無需學習它們在套件階層中的位置。它提供了簡潔的方式,將匯入類別與套件的語句簡化成匯入模組,以減少樣板程式碼撰寫:
- 引入新的
import module
語句,允許一次性匯入模組中的所有型別。例如:import module java.base;
將匯入java.base
模組中導出的所有套件 - 新語句可以與現有的
import
語句共存,並且不會影響現有程式碼的行為
JEP 495:簡單原始檔和實例主方法(第四次預覽)
- 本站介紹:JDK 23 功能:JEP 477 隱式宣告類別和實例主方法的革新之路(規格未變更故延用前版介紹)
- 官方介紹:Simple Source Files and Instance Main Methods (Fourth Preview)
本功能讓初學者能夠輕鬆地撰寫第一個 Java 程式,而不需要先全部理解較為複雜的程式語法和功能。簡易的程式可以使用精簡的宣告方式運行,並且在需要時能夠無縫擴展去使用更高級的功能。經驗豐富的開發人員也可以享受簡潔地編寫小型程式的樂趣。
- 隱式宣告類別:如果一個簡單 Java 原始檔中沒有使用
class
關鍵字明顯地宣告任何類別,編譯器會自動為該檔案建立一個隱式類別。類別名稱與檔案名稱相同(但不包括.java
副檔名),並且它會是final
且直接繼承自Object
- 實例主方法:允許在隱式宣告類別中定義一個非靜態的
main
方法,其方法簽章為void main()
或void main(String[] args)
- 自動匯入:隱式宣告類別會自動
import module java.base
模組中的所有型別(請參考上一節模組匯入宣告的內容) - 新增輸入輸出方法:新增並且
import static java.io.IO.*;
以提供println(Object o)
、print(Object o)
、String readln(String prompt)
方法(Java 23),以及println()
和String readln()
方法(Java 24 新增)
JEP 492:彈性建構式主體(第三次預覽)
- 本站介紹:JDK 23 功能預覽:JEP 482 彈性建構式主體設計(規格未變更故延用前版簡介)
- 官方介紹:Flexible Constructor Bodies (Third Preview)
開發人員可以更自由地操作建構函式的行為,本功能允許一些特定的語句在明確的建構式呼叫(即 super(..)
或 this(..)
)之前出現。因為它允許將判斷邏輯放在呼叫父類別的建構式之前,從而避免了將某些檢查和初始化邏輯分解到靜態方法和中間建構式中的必要。例如:如果建構式可以在呼叫父類別建構式之前先行驗證參數,那麼當參數無效時就能夠拋出異常並避免不必要的父類別實例化。
- 提高可靠性:在呼叫父類別建構式或其他建構式之前檢查初始化欄位,確保衍生類別的狀態在父類別建構式執行時就已經準備就緒,以避免潛在的錯誤。尤其在方法覆寫的情況下,能確保子類別的欄位狀態在父類別方法執行前已經正確初始化
- 程式碼更清晰:將欄位初始化邏輯集中在建構函式開頭,使程式碼結構更清晰,易於閱讀和維護
它讓 Java 建構式更加靈活,允許在調用其他建構式之前先初始化操作,從而提高程式碼的可靠性和可維護性。然而,開發人員在使用此功能時需要注意其潛在的複雜性和錯誤風險,並確保相容現有的程式碼。
函式庫
JEP 484:類別檔案 API(預覽轉正式)
- 本站介紹:正式版介紹待補、JDK 23 功能預覽:JEP 466 Class-File API 類別檔案存取(前版預覽簡介)
- 官方介紹:Class-File API
本 JEP 提供了一個用於解析、生成和轉換 Java 類別檔案的 API,並會依照 Java 虛擬機器規格所定義的格式做定期更新。此 API 可以緩解 Java 每六個月發布週期所帶來的窘境,因為快速發布迫使支援操作類別檔的函式庫需要快速反應以支援每個新的 Java 類別檔案版本。當此功能最終確定後,它可以讓 JDK 本身擺脫對第三方 ASM 程式庫的依賴。
它提供了標準化的 Java API 去簡化處理類別檔案的任務,使開發人員能夠更輕鬆地解析、修改、生成和轉換 Java 的類別檔案:
- 解析:將類別檔案中的資訊(例如常數池、欄位、方法、屬性等)表示為不可變的 Java 物件,方便開發人員進行存取和操作
- 生成:提供 Builder 來協助開發人員逐步構建類別檔案,並將其寫入輸出流或檔案
- 轉換:允許開發人員修改現有的類別檔案,例如替換或刪除其中的元素
JEP 489:向量 API(第九次孵化)
- 本站介紹:JDK 23 功能預覽:JEP 469 Vector API 向量計算(說明未變更故延用前版簡介)
- 官方介紹:Vector API (Ninth Incubator)
開發人員可以使用 Vector API 去描述和表示向量計算。在支援的 CPU 架構上,於運行時能夠可靠地編譯成最佳向量指令,從而實現優於等效標量計算的性能。預計這個 API 將持續孵化(最多只進行少量更改)直到來自 Project Valhalla 的必要功能(基於值的類別和物件)成為預覽功能為止。
- 引入一個 API 來清晰簡潔地表達各種向量計算,包括在循環內組成的向量操作序列,可能還包括控制流
- 平台獨立:API 應該獨立於 CPU 架構,並能夠在支援向量指令的多個架構上實現
- 提供了一組類別和方法,用於建立、操作和訪問向量
- 支援各種向量操作,例如:加減乘除、比較、邏輯運算等
JEP 485:串流聚集器(預覽轉正式)
- 本站介紹:串流聚集器詳細介紹待補、JDK 23 功能:JEP 473 Stream Gatherer 串流聚集器(規格未變更故延用前版介紹)
- 官方介紹:Stream Gatherers
這個功能讓 Stream API 能夠支援自定義的中間操作,使得串流管道能夠以現有的內建操作轉換資料。Stream gatherers 為中間操作提供了與終端收集器(collector
)同樣多的靈活性,總共有五個內建的聚集器。它的目標如下:
- 引入新的中間串流操作
Stream::gather(Gatherer)
,透過使用者定義的實體(聚集器 gatherer)來處理串流的元素 - Gatherer 代表串流元素的轉換,它的介面是
java.util.stream.Gatherer
,可以一對一、一對多、多對一或多對多的方式轉換 - 可以構建高效、並行的串流,實現幾乎任何中間操作
Stream::gather(Gatherer)
之於中間操作,就像Stream::collect(Collector)
之於終端操作
JEP 499:結構化並行處理(第四次預覽)
- 本站介紹:JDK 23 功能預覽:JEP 480 結構化並行(規格未變更故延用前版簡介)
- 官方介紹:Structured Concurrency (Fourth Preview)
結構化並行處理能讓開發者將一組相關任務(運行在不同執行緒上)視為單一的工作單元,從而簡化錯誤處理和取消操作、提升可靠性,並加強可觀察性。這個 API 提倡一種並行編程風格,可以消除因取消和關閉而產生的常見風險,如執行緒洩漏和取消延遲。
- 簡化並行程式設計,特別是在使用虛擬執行緒時
- 提供一種結構化、可預測且易於推理的並行程式模型
- 引入
StructuredTaskScope
類別以允許開發者將一個任務發展成一組並行的子任務且同時能彼此協調:fork()
方法:創建和啟動子任務,並返回子任務的結果join()
方法:等待所有子任務完成,並處理任何異常- 支援自動取消子任務:如果父任務被取消,則所有子任務也會被自動取消
- 確保子任務在其父任務完成之前完成,並集中處理異常
- 支援範圍值(JEP 487 Scoped Values)的繼承:子任務可以繼承父任務的範圍值綁定,從而簡化資料共享
JEP 487:範圍值(第四次預覽)
- 本站介紹:預覽更新版簡介待補、JDK 23 功能:JEP 481 範圍值是更安全且高效的資料共享方式
- 官方介紹:Scoped Values (Fourth Preview)
允許一個方法在執行緒內安全且有效率地與它的被調用者(無論是直接或間接調用)以及子執行緒共享不可變的資料。範圍值(Scoped values)比執行緒局部變數(thread-local variables)更容易理解,特別是和虛擬執行緒(JEP 444)和結構化並行處理(JEP 499)一起使用時。它們具有更低的空間和時間成本。
- 引入
ScopedValue
類型,作為共享資料的容器 - 提供
ScopedValue.where(key, value).run(op)
語句 ,將ScopedValue
與特定值綁定,並在該綁定範圍內執行程式碼 - 子執行緒可以繼承父執行緒的
ScopedValue
綁定
安全性
JEP 472:限制 JNI 使用的準備工作
- 本站介紹:正式版介紹待補、JDK 24 的首項公開功能 JEP 472 為限制使用 JNI 做準備(簡介)
- 官方介紹:Prepare to Restrict the Use of JNI
本功能是「限制 Java Native Interface 使用」的準備工作。只要使用 JNI 時,JVM 就會發出警告。JDK 22 中引入的外部函式和記憶體 API(JEP 454 Foreign Function & Memory API,作為 JNI 替代方案)也同樣包含在內,因此使用 FFM API 時也會發出警告。其目的是幫助我們為未來的 Java 版本做好準備,並透過統一限制 JNI 和 FFM API 的使用來確保預設情況下的完整性。我們在必要時可以透過選擇性地指定選項來避免產生警告(現在階段)和禁止執行的限制(未來階段)。
- 保留 JNI 作為與原生程式碼相互操作的標準方式
- 預設不允許與原生程式碼互動,無論是使用 JNI 或 FFM API,除非我們在程式啟動時明確指定啟用 JNI 或 FFM API
- 調整 JNI 和 FFM API 的使用,讓函式庫的維護人員能順利轉移而無需開發人員變更命令列選項
- 它並非要棄用 JNI,也並非要從 Java 平台中移除 JNI,同時也沒有要限制 JNI 呼叫原生程式碼
JEP 478:密鑰派生函數 API(首次預覽)
- 本站介紹:預覽版簡介待補
- 官方介紹:Key Derivation Function API (Preview)
引入密鑰派生函數(Key Derivation Functions、KDFs)的 API,它是一種用於從密鑰和其他數據派生出其他金鑰的密碼演算法,應用於加密和身份驗證。它有下列幾個重要的目標:
- 讓程式能使用 KDF 演算法,例如:基於 HMAC 的提取和擴展金鑰衍生函數(HKDF,RFC 5869)和 Argon2(RFC 9106)
- 在金鑰封裝機制(Key Encapsulation Mechanism、KEM,JEP 452)的實現中、更高級別的協定(例如 TLS 1.3 中的混合金鑰交換)中、以及在密碼方案(例如混合公鑰加密(Hybrid Public Key Encryption、HPKE,RFC 9180)中,實現 KDF 的應用
- 允許安全提供者用 Java 程式碼或原生程式碼實現 KDF 演算法
- 包括 HKDF 的實現並引入其他特定於 HKDF 的 API
JEP 486:永久停用安全管理器
- 本站介紹:正式版介紹待補
- 官方介紹:Permanently Disable the Security Manager
有鑑於 Security Manager 已不再是保護客戶端程式碼的主要方式,也很少用於保護伺服器端的程式碼,因此在 Java 17 時已被標記棄用(JEP 411)。本功能作為移除 Security Manager 的下一步,目標將修改 Java 平台規範使開發者無法啟用它,並且其他平台類別也不再引用它。此更改對絕大多數的應用程式、函式庫和工具不會造成影響。
- 移除在 Java 執行時啟用 Security Manager 的能力(
java -Djava.security.manager...
) - 移除在程式執行中安裝 Security Manager 的能力(
System.setSecurityManager(...)
) - 改進目前將資源存取決策委託給 Security Manager 的數百個 JDK 類別的可維護性
- 修改 Security Manager API 的規範,以便它的所有實現都表現得好像從未啟用過 Security Manager
- 在此版本中仍會保留 Security Manager API,以便依賴於它的現有程式碼的維護者有足夠時間遷移
JEP 496:基於模格的抗量子金鑰封裝機制
- 本站介紹:正式版介紹待補
- 官方介紹:Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism
提供抗量子模格金鑰封裝機制(ML-KEM)的實現來增強 Java 應用程式的安全性。金鑰封裝機制(KEM)使用公鑰密碼學透過不安全的通訊通道保護對稱金鑰。ML-KEM 旨在抵禦未來的量子計算攻擊,它已由美國國家標準與技術研究院)NIST)在 FIPS 203 中標準化。
- 提供
KeyPairGenerator
、KEM
和KeyFactory
API 的 ML-KEM 實現,並支援 FIPS 203 中標準化的參數集 ML-KEM-512、ML-KEM-768 和 ML-KEM-1024
JEP 497:基於模格的抗量子數位簽章演算法
- 本站介紹:正式版介紹待補
- 官方介紹:Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm
提供抗量子模格數位簽章演算法(ML-DSA)的實現來增強 Java 應用程式的安全性。數位簽章用於檢測對資料的未經授權的修改,並驗證簽名者的身份。 ML-DSA 旨在抵禦未來的量子計算攻擊,它已由美國國家標準與技術研究院(NIST)在 FIPS 204 中標準化。
- 提供
KeyPairGenerator
、Signature
和KeyFactory
API 的 ML-DSA 實現,並支援 FIPS 204 中標準化的參數集 ML-DSA-44、ML-DSA-65 和 ML-DSA-87
JEP 498:對使用 sun.misc.Unsafe
中的記憶體存取方法發出警告
- 本站介紹:正式版介紹待補、JDK 23 功能:JEP 471 棄用 sun.misc.Unsafe 中的記憶體存取方法
- 官方介紹:Warn upon Use of Memory-Access Methods in sun.misc.Unsafe
在 JDK 23 中,sun.misc.Unsafe
的記憶體存取方法已被標記為棄用,並且由標準 API 所取代,也就是 VarHandle
API(JEP 193,JDK 9)和外部函數和記憶體 API(JEP 454,JDK 22)。藉由本功能的變更,之後當程式第一次使用這些不受支援的方法時,執行環境會發出警告。
本 JEP 是 JEP 471 的後續。JEP 471 棄用了 sun.misc.Unsafe
的記憶體存取方法,使其能夠在之後的版本中移除,並描述了逐步移除的過程。
性能
JEP 404:分代 Shenandoah 垃圾收集器(實驗性)
- 本站介紹:正式版介紹待補
- 官方介紹:Generational Shenandoah (Experimental)
強化 Shenandoah (仙納度)垃圾收集器,使其擁有實驗性的分代收集能力,以提高可持續的吞吐量、負載高峰彈性和記憶體利用率。本功能的主要目標是提供實驗性的分代模式,且不會影響未分代的 Shenandoah。未來的版本中預計將分代模式設為預設選項。
JEP 450:壓縮物件標頭 (實驗性)
- 本站介紹:正式版介紹待補
- 官方介紹:Compact Object Headers (Experimental)
本功能透過刪除物件標頭中的未使用空間和壓縮標頭資訊來減少物件記憶體佔用。它是一種新的記憶體布局,可以節省記憶體空間並提高效能。在 64 位元架構上,將 HotSpot JVM 中的物件標頭尺寸從 96 至 128 位元減少到 64 位元。這將減少堆積的大小並提高部署密度,增加資料局部性。
- 將目標 64 位元平台(x64 和 AArch64)上的物件標頭尺寸減少到 64 位元(8 位元組)
- 減少實際工作負載上的物件大小和記憶體佔用
- 不會在目標 64 位元平台上產生超過 5% 的吞吐量或延遲開銷
- 僅在極少數情況下,不會在非目標 64 位元平台上產生可測量的吞吐量或延遲開銷
JEP 475:G1 垃圾收集器的屏障擴展機制
- 本站介紹:正式版介紹待補
- 官方介紹:Late Barrier Expansion for G1
改善 G1 垃圾回收器的屏障(用於記錄應用程式記憶體存取資訊)擴展機制,從 C2 JIT 編譯管道的早期階段移至後期階段以簡化其實作。
- 當使用 G1 垃圾回收器時,可減少 C2 的執行時間
- 讓不了解 C2 的 HotSpot 開發人員也能夠理解 G1 屏障
- 保證 C2 保留關於記憶體存取、安全點和屏障的相對順序其不變性
- 在速度和大小方面,維持 C2 生成程式碼的品質
JEP 483:預先類別的載入和連結功能
- 本站介紹:正式版介紹待補
- 官方介紹:Ahead-of-Time Class Loading & Linking
在 HotSpot Java 虛擬機器啟動時,將應用程式的類別以載入和連結的狀態立即載入,以縮短啟動時間。我們可以先執行一次應用程式並開啟監控,將所有類別的載入和連結形式都儲存在快取中以供後續運行使用。
- 因為大多數程式每次執行時的啟動方式大致相同,所以可用來縮短啟動時間
- 不會對應用程式、函式庫或框架的程式碼進行任何更改
- 不會修改 java 的命令列啟動方式,除了與此功能直接相關的命令列選項之外
- 不需要使用 jlink 或 jpackage 工具
JEP 490:移除 ZGC 垃圾收集器的未分代模式
- 本站介紹:正式版介紹待補、JDK 23 功能:JEP 474 ZGC 預設將改為分代模式
- 官方介紹:ZGC: Remove the Non-Generational Mode
本功能為移除 Z 垃圾收集器的未分代模式,以減少支援分代和未分代這兩種模式所帶來的維護成本。
JEP 491:同步虛擬執行緒時的解綁機制
- 本站介紹:正式版介紹待補
- 官方介紹:Synchronize Virtual Threads without Pinning
虛擬執行緒在 synchronized
區塊或方法中被阻塞時,因為不會解除與底層的平台執行緒之間的綁定(pinned)關係,使得平台執行緒無法被釋放來執行其他已經準備好運行的虛擬執行緒,造成大量的虛擬執行緒需要同步時會導致效能瓶頸。
本功能讓 synchronized
方法和語句中阻塞的虛擬執行緒可以釋放其底層平台執行緒,以便其他虛擬執行緒能夠使用。這幾乎能夠消除虛擬執行緒被固定到平台執行緒的所有情況,尤其是它嚴重限制了用於處理工作負載的虛擬執行緒數量。
- 使現有的 Java 函式庫能夠在不修改
synchronized
方法和語句的情況下與虛擬執行緒之間良好地合作 - 改進識別虛擬執行緒無法釋放平台執行緒的剩餘情況的診斷
內建工具
JEP 493:不需 JMOD 檔案的執行時期映像連結功能
- 本站介紹:正式版介紹待補
- 官方介紹:Linking Run-Time Images without JMODs
允許 jlink 工具在不使用 JDK 的 JMOD 檔案的情況下,能創建自定義執行時期的映像檔,可將 JDK 的大小減少約 25%。構建 JDK 時必須啟用此功能;預設情況下不會啟用它,並且某些 JDK 供應商可能會選擇不啟用它。
- 使用者可以從模組連結執行時期映像檔,無論這些模組是獨立的 JMOD 檔案、模組化 JAR 檔案,還是先前連結的運行時映像的一部分
管理工作
JEP 479:移除 Windows 32 位元的 x86 平台支援
- 本站介紹:正式版介紹待補
- 官方介紹:Remove the Windows 32-bit x86 Port
移除對 Windows 32 位元 x86 平台的支援。
JEP 501:棄用 32 位元的 x86 平台
- 本站介紹:正式版介紹待補
- 官方介紹:Deprecate the 32-bit x86 Port for Removal
棄用 32 位元 x86 平台支援,以便在未來的版本中移除。本功能會棄用 Linux 32 位元 x86 平台,這也是 JDK 中唯一僅存的 32 位元 x86 平台。實際上,它還會棄用任何僅存的下游平台。在移除之後,與架構無關的 Zero 平台將是在 32 位元 x86 處理器上運行 Java 程式的唯一方式。
- 需要平台特定支援的新功能再也不必支援 32 位元 x86 平台
- 在相關文件、配置腳本和測試作業中,將該平台與相關的特定功能都標記為已棄用,以便將來移除
總結
Java 24 候選版本中的功能代表了 Java 在效能、安全和開發便利性等方面的持續進步,特別是在量子電腦安全性和記憶體管理效能方面的改進,展現了面對未來技術挑戰時的前瞻性思維。
隨著這些新功能的加入,Java 生態系將變得更加完整。我們可以利用這些新特性來構建更安全、更高效的應用程式,同時也為未來的技術發展做好準備。大家請一起期待這些改進能為 Java 社群帶來更多創新的可能性!
本篇文章的內容為老喬原創、二創或翻譯而來。雖已善盡校對、順稿與查核義務,但人非聖賢,多少仍會有疏漏之處難以避免。如果大家有任何問題、建議或指教,都歡迎在底下留言與老喬討論!