
Java 教程
- Java - 首頁
- Java - 概述
- Java - 歷史
- Java - 特性
- Java 與 C++
- JVM - Java 虛擬機器
- Java - JDK vs JRE vs JVM
- Java - Hello World 程式
- Java - 環境搭建
- Java - 基本語法
- Java - 變數型別
- Java - 資料型別
- Java - 型別轉換
- Java - Unicode 系統
- Java - 基本運算子
- Java - 註釋
- Java - 使用者輸入
- Java - 日期和時間
Java 控制語句
- Java - 迴圈控制
- Java - 決策制定
- Java - If-else
- Java - Switch
- Java - For 迴圈
- Java - For-Each 迴圈
- Java - While 迴圈
- Java - do-while 迴圈
- Java - Break
- Java - Continue
面向物件程式設計
- Java - OOPs 概念
- Java - 物件和類
- Java - 類屬性
- Java - 類方法
- Java - 方法
- Java - 變數作用域
- Java - 建構函式
- Java - 訪問修飾符
- Java - 繼承
- Java - 聚合
- Java - 多型
- Java - 重寫
- Java - 方法過載
- Java - 動態繫結
- Java - 靜態繫結
- Java - 例項初始化塊
- Java - 抽象
- Java - 封裝
- Java - 介面
- Java - 包
- Java - 內部類
- Java - 靜態類
- Java - 匿名類
- Java - 單例類
- Java - 包裝類
- Java - 列舉
- Java - 列舉建構函式
- Java - 列舉字串
Java 內建類
Java 檔案處理
Java 錯誤和異常
- Java - 異常
- Java - try-catch 塊
- Java - try-with-resources
- Java - 多重 catch 塊
- Java - 巢狀 try 塊
- Java - Finally 塊
- Java - throw 異常
- Java - 異常傳播
- Java - 內建異常
- Java - 自定義異常
Java 多執行緒
- Java - 多執行緒
- Java - 執行緒生命週期
- Java - 建立執行緒
- Java - 啟動執行緒
- Java - 執行緒連線
- Java - 執行緒命名
- Java - 執行緒排程器
- Java - 執行緒池
- Java - 主執行緒
- Java - 執行緒優先順序
- Java - 守護執行緒
- Java - 執行緒組
- Java - 關閉鉤子
Java 同步
Java 網路
- Java - 網路
- Java - 套接字程式設計
- Java - URL 處理
- Java - URL 類
- Java - URLConnection 類
- Java - HttpURLConnection 類
- Java - Socket 類
- Java - 泛型
Java 集合
Java 介面
Java 資料結構
Java 集合演算法
高階 Java
- Java - 命令列引數
- Java - Lambda 表示式
- Java - 傳送郵件
- Java - Applet 基礎
- Java - Javadoc 註釋
- Java - 自動裝箱和拆箱
- Java - 檔案不匹配方法
- Java - REPL (JShell)
- Java - 多版本 Jar 檔案
- Java - 私有介面方法
- Java - 內部類菱形運算子
- Java - 多解析度影像 API
- Java - 集合工廠方法
- Java - 模組系統
- Java - Nashorn JavaScript
- Java - Optional 類
- Java - 方法引用
- Java - 函式式介面
- Java - 預設方法
- Java - Base64 編碼解碼
- Java - Switch 表示式
- Java - Teeing 收集器
- Java - 微基準測試
- Java - 文字塊
- Java - 動態 CDS 存檔
- Java - Z 垃圾收集器 (ZGC)
- Java - 空指標異常
- Java - 打包工具
- Java - 密封類
- Java - 記錄類
- Java - 隱藏類
- Java - 模式匹配
- Java - 簡潔數字格式化
- Java - 垃圾回收
- Java - JIT 編譯器
Java 雜項
- Java - 遞迴
- Java - 正則表示式
- Java - 序列化
- Java - 字串
- Java - 程序 API 改進
- Java - 流 API 改進
- Java - 增強的 @Deprecated 註解
- Java - CompletableFuture API 改進
- Java - 流
- Java - 日期時間 API
- Java 8 - 新特性
- Java 9 - 新特性
- Java 10 - 新特性
- Java 11 - 新特性
- Java 12 - 新特性
- Java 13 - 新特性
- Java 14 - 新特性
- Java 15 - 新特性
- Java 16 - 新特性
Java API 和框架
Java 類引用
- Java - Scanner
- Java - 陣列
- Java - 字串
- Java - Date
- Java - ArrayList
- Java - Vector
- Java - Stack
- Java - PriorityQueue
- Java - LinkedList
- Java - ArrayDeque
- Java - HashMap
- Java - LinkedHashMap
- Java - WeakHashMap
- Java - EnumMap
- Java - TreeMap
- Java - IdentityHashMap
- Java - HashSet
- Java - EnumSet
- Java - LinkedHashSet
- Java - TreeSet
- Java - BitSet
- Java - Dictionary
- Java - Hashtable
- Java - Properties
- Java - Collection
- Java - Array
Java 有用資源
Java - 多版本 Jar 檔案
多版本 JAR 功能在 Java 9 中引入。它允許使用與多個 Java 版本相關的多個版本的類。例如,許多第三方庫或框架使用 Java。由於 Java 作為一門語言不斷發展,並且每個主要版本都會向該語言新增許多新功能。由於第三方庫/框架必須重寫其程式碼庫以適應新功能,因此團隊極不情願使用新功能。這阻礙了他們遷移到新的Java 版本。
為了解決維護同一檔案的多原始碼或特定於平臺的檔案版本的問題,引入了多版本 JAR 功能。請考慮以下示例
一個典型的 jar 檔案將所有類都放在根級別。
jar root - Calculator.class - Util.class - Math.class - Service.class
如果我們有 Java 9 功能特定的Util 類,則該 jar 無法在 JRE 8 或更低版本中使用。
在多版本 Jar 中,格式已增強,可以維護和使用特定於平臺的不同版本的Java 類 或資源。在 JAR 中,檔案 MANIFEST.MF 檔案在其主部分中有一個條目 Multi-Release: true。META-INF 目錄還包含一個 versions 子目錄,其子目錄(從 Java 9 開始為 9)儲存特定於版本的類和資原始檔。
使用 MANIFEST.MF,我們可以將特定於 Java 9 或更高版本的類指定在不同的位置,如下所示
Java 多版本 Jar 檔案目錄結構
jar root - Calculator.class - Util.class - Math.class - Service.class META-INF - versions - 9 - Util.class - Math.class - 10 - Util.class - Math.class
現在,如果 JRE 不支援多版本 jar,則它將選擇根級別的類進行載入和執行,否則將載入特定於版本的類。例如,如果上述 jar 在 Java 8 中使用,則將使用根級別的 Util.class。如果同一 jar 由 Java 9 執行,則將選擇 Java 9 特定版本的類,依此類推。這樣,第三方庫/框架可以支援新功能,而無需更改針對較低版本編寫的原始碼。
在 Java 中建立和使用多版本 Jar 檔案
在此示例中,我們將建立和使用一個多版本 jar,以使 Tester.java 檔案有兩個版本,一個用於 jdk 7,一個用於 jdk 9,並在不同的 jdk 版本上執行它。
以下是在 Java 中建立和使用多版本 jar 檔案的步驟:
步驟 1:建立 Java 7 特定的 Java 類
讓我們建立一個 Java 類,該類可能包含 Java 7 特定的程式碼和功能,這些功能在 Java 9 之前不可用。在此示例中,我們只是簡單地列印一條訊息以展示此功能的使用。
建立一個資料夾 c:/test/java7/com/tutorialspoint。建立包含以下內容的 Tester.java:
Tester.java
這是一個簡單的程式碼,當程式執行時,我們將列印一條 Java 7 特定的訊息。
package com.tutorialspoint; public class Tester { public static void main(String[] args) { System.out.println("Inside java 7"); } }
步驟 2:建立 Java 9 特定的 Java 類
讓我們建立一個 Java 類,該類可能包含特定於 Java 9 增強的程式碼和功能,這些功能在 Java 9 之前不可用。在此示例中,我們只是簡單地列印一條訊息以展示此功能的使用。
建立資料夾 c:/test/java9/com/tutorialspoint。建立 Tester.java 檔案,內容如下:
Tester.java
這與上面的程式碼類似,在程式執行時列印 Java 9 特定的訊息。
package com.tutorialspoint; public class Tester { public static void main(String[] args) { System.out.println("Inside java 9"); } }
為了使用多版本 jar 功能,必須確保兩個類的簽名相同。公共介面(例如方法簽名)在兩個類中應該相同。
步驟 3:使用目標版本編譯
C:\test > javac --release 9 java9/com/tutorialspoint/Tester.java C:\JAVA > javac --release 7 java7/com/tutorialspoint/Tester.java
步驟 4:建立多版本 JAR
C:\JAVA > jar -c -f test.jar -C java7 . --release 9 -C java9. Warning: entry META-INF/versions/9/com/tutorialspoint/Tester.java, multiple resources with same name
步驟 5:使用 JDK 7 執行 JAR
C:\JAVA > java -cp test.jar com.tutorialspoint.Tester Inside Java 7
步驟 6:使用 JDK 9 執行 JAR
C:\JAVA > java -cp test.jar com.tutorialspoint.Tester Inside Java 9
結論
我們可以看到,使用多版本 Jar 功能,可以在不影響向後相容性的情況下建立類的多個版本。我們展示了可以使用相同的命令來執行一個類。根據 META-INF 檔案中列出的 JRE 版本,會選擇相應的類。如果 JRE 版本較低,不支援多版本 jar,則會選擇根級別的類,而不是版本特定的類。最後,版本化類的公共方法的簽名應該相同,以便此功能能夠完美執行。