您的搜尋未與任何結果相符。
以下操作有助您找到所需內容,建議您不妨一試:
它們是什麼以及如何使用它們
作者:Paul Deitel
Paul Deitel
在本文中,我將介紹 Java 9 Platform Module System (JPMS),這是自 Java 誕生以來非常重要的新軟體工程技術。模組化是 Project Jigsaw 的成果,可協助所有層級的開發人員在建置、維護和發展軟體系統 (尤其是大型系統) 時提高工作效率。
模組化在套裝程式之上添加較高的聚總層級。關鍵的新語言元素是模組,它是一組專屬命名、可重用的相關套裝程式、資源 (例如圖像和 XML 檔案) 和模組描述符,用於指定:
Java SE 平台自 1995 年誕生以來,目前約獲 1 千萬名開發人員用來為物聯網 (IoT) 和其他嵌入式裝置等受資源限制的裝置建置各種小型應用程式,到大規模業務關鍵型和任務關鍵型系統。市面上有大量的舊有代碼,但到目前為止,Java 平台主要是單一的通用解決方案。多年來,人們針對模組化 Java 做出了各種努力,但沒有一個被廣泛應用,也沒有一個可以用於模組化 Java 平台。
實現 Java SE 平台的模組化充滿挑戰性,並且投入了大量的時間。JSR 277:Java Module System 最初於 2005 年針對 Java 7 推出,之後被 JSR 376:Java Platform Module System 取代,作為 Java 8 的目標,直到 Java 9 延遲到 2017 年 9 月推出之後,Java SE 平台在 Java 9 中進行了模組化。
每個模組都必須明確指出其相依性。
根據 JSR 376,對 Java SE 平台進行模組化的主要目標是:
JEP 200:THE MODULAR JDK
JEP 201:MODULAR SOURCE CODE
JEP 220:MODULAR RUN-TIME IMAGES
JEP 260:ENCAPSULATE MOST INTERNAL APIS
JEP 261:MODULE SYSTEM
JEP 275:MODULAR JAVA APPLICATION PACKAGING
JEP 282: JLINK:THE JAVA LINKER
JSR 376:JAVA PLATFORM MODULE SYSTEM
JSR 379:JAVA SE 9
表 1.Java 模組化 JEP 和 JSR
Java 9 的關鍵概念是將 JDK 分成支援各種組態的模組。(參閱「 JEP 200:The Modular JDK」。表 1 顯示了與 Java 模組化有關的所有 JEP 和 JSR。)使用 JDK bin 資料夾中的 java 命令配搭 --list-modules
選項,如下所示:
java -- list-modules
列出 JDK 的模組集,其中包括實行 Java 語言 SE 規格 (以 java
為開頭的名稱)、JavaFX 模組 (以 javafx
為開頭的名稱)、JDK 特定模組 (以 jdk
為開頭的名稱) 以及 Oracle 特定模組 (以 oracle
為開頭的名稱)。每個模組名稱後面跟著一個版本字串 — @9
表示該模組屬於 Java 9。
如上所述,模組必須提供模組描述元,指定模組的相依性、模組提供給其他模組使用的套裝程式等等。模組描述元是模組宣告的編譯版本,定義在名為 module-info.java
的檔案中。每個模組宣告都是以關鍵字 module
開頭,後面跟著唯一的模組名稱和以大括號括住的模組主體,如下所示:
模組系統的關鍵動機是強封裝。
module modulename {
}
模組宣告的主體可以是空的,也可以包含各種模組指令,包括 requires
、exports
、provides…with
、uses
和 opens
(我們討論的每個指令)。如稍後所見,編譯模組宣告會建立模組描述區,該描述區儲存在模組根資料夾中名為 module-info.class
的檔案中。在這裡,我們簡要介紹每個模組指令。之後,我們將呈現實際的模組宣告。
關鍵字 exports
、module
、open
、opens
、provides
、requires
、uses
、with
以及我們稍後介紹的 to
和 transitive
都是受限的關鍵字。這些僅是模組宣告中的關鍵字,並且可以在程式碼中的其他任何地方用作識別碼。
requires。requires
模組指令指定此模組相依於其他模組 ,此關係稱為模組相依性。每個模組都必須明確聲明其相依性。當模組 A requires
模組 B 時,稱為模組 A 讀取模組 B,模組 B 被模組 A 讀取。若要指定其他模組的相依性,請使用 requires
,如下所示:
requires modulename;
另外還有一個 requires static
指令,用來指示在編譯時是必需的,但在程式實際執行時是可選的。這稱為選擇性相依項,但不會在本介紹中討論。
requires transitive — 隱式可讀性。若要指定其他模組的相依性,並確保其他模組讀取您的模組時也會讀取隱式可讀性,請使用 requires transitive
(如下所示):
requires transitive modulename;
請考慮 java.desktop
模組宣告中的下列指令:
requires transitive java.xml
;
在此情況下,任何讀取 java.desktop
的模組也會隱式讀取 java.xml
。例如,如果 java.desktop
模組中的方法傳回模組中的類型 java.xml
,則讀取的模組中的程式碼 java.desktop
將變得依賴 java.xml
。如果 java.desktop
模組宣告中沒有 requires transitive
指令,除非這些相關模組顯式讀取 java.xml
,否則這些模組將不會編譯。
根據 JSR 379,Java SE 的標準模組在任何情況下都必須具備隱含的可讀性,如此處所述。此外,雖然 Java SE 標準模組可能依賴非標準模組,但不得將隱含的可讀性授予這些模組。這確保了僅依賴 Java SE 標準模組的程式碼可以跨 Java SE 導入移植。
exports 及 exports…to。exports
模組指令指定模組的套裝程式之一,其 public
類型 (及其巢狀 public
和 protected
類型) 應可供所有其他模組中的程式碼存取。exports…to
指令可讓您精確地指定哪些模組或模組的程式碼可以存取匯出的套裝程式,這稱為合格匯出。
uses。uses
模組指令指定此模組所使用的服務,讓此模組成為服務使用者。service 是類別物件,用於實行介面或擴展 uses
指令中指定的 abstract
類別。
provides…with。provides…with
模組指令指定模組提供服務實作,讓模組成為服務提供者。指令的 provides
部分指定模組的 uses
指令中列出的介面或 abstract
類別,而指令的 with
部分指定服務提供者類別的名稱,該名稱是 implements
介面或 extends
abstract
類別。
open、opens 及 opens…to。在 Java 9 之前,reflection 可用於瞭解套裝程式中的所有類型以及類型的所有成員 (甚至是其 private
成員) ,無論您是否允許此功能。因此,沒有任何東西被真正封裝。
模組系統的關鍵優勢是強封裝。預設情況下,模組中的類型無法供其他模組存取,除非其為公用類型且您匯出其套裝程式。您僅公開您想要公開的套裝程式。在 Java 9 中,這也適用於 reflection。
允許僅限程式實際執行存取套裝程式。open 模組指令的形式
opens package
指示特定套裝程式的 public
類型 (及其巢狀 public
和 protected
類型) 只能在程式實際執行時,供其他模組中的程式碼存取。此外,指定套裝程式中的所有類型 (以及所有類型的成員) 都可透過 reflection 存取。
允許特定模組僅執行程式實際執行存取套裝程式。opens…to
模組指令的形式
opens package to comma-separated-list-of-modules
指示特定套裝程式的 public
類型 (及其巢狀 public
和 protected
類型) 只能在程式實際執行時,供列示模組中的程式碼存取。指定套裝程式中的所有類型 (以及所有類型的成員) 皆可透過 reflection 指定模組中的程式碼來存取。
允許程式實際執行存取模組中的所有套裝程式。如果指定模組中的所有套裝程式皆可在執行時期存取,並透過 reflection 讓所有其他模組存取,那麽您可以存取 open
整個模組,如下所示:
open module modulename {
// module directives
}
依照預設,具有套裝軟體程式實際執行反射存取權的模組會看到套裝軟體的 public
類型 (及其巢狀 public
和 protected
類型)。不過,其他模組中的程式碼可以存取公開之套裝程式中的所有類型,以及這些類型內的所有成員,包括透過 setAccessible
存取 private
成員 (如較早的 Java 版本)。
如需有關 setAccessible
和 reflection 的詳細資訊,請參閱 Oracle 文件。
Paul Deitel 是 Deitel & Associates 執行長兼技術長,畢業于麻省理工學院,擁有 35 年的運算經驗。他是 Java Champion,擁有超過 22 年的 Java 程式設計經驗。他和合著者 Harvey M. Deitel 博士是世界上最暢銷的程式語言書籍的作者。Paul 為全球產業、政府和學術界的客戶提供 Java、Android、iOS、C#、C++、C 和網際網路程式設計課程。
註:本文摘自《Java Magazine》,2017 年 9 月 /10 月。