個人博客 轉載請註明原創出處。
從Java 9
開始,在Java
的世界裏多了一個叫模塊(JSR376)的特性。模塊系統的前身是Jigsaw
項目。最初,該項目僅僅是爲JDK
設計、實現一個模塊系統。後來項目組也但願它能爲開發者所用——雖然,一開始它並非Java SE
平臺規範的組成部分。隨着項目的不斷深刻,Java
平臺對標準模塊系統的呼求也日益增加,JCP
批准該項目升級爲JavaSE
平臺的一部分,也能服務於Java ME
和Java EE
平臺的需求。java
Java
平臺模塊系統是這樣描述的:Java
編程組件,即模塊。它是自描述的代碼與數據的集合,有如下特性:javac
、jlink
增長了一些選項,以及在Java
中,你能夠指定模塊路徑,這些路徑定位模塊的定義。JAR
文件,該文件是一個JAR
文件,其根目錄中包含module-info.class
文件。JMOD
格式,它是一種相似於JAR
的打包格式,但它能夠包含原生代碼和配置文件。使你可以將JDK
的模塊組合成各類配置,包括:編程
JRE
和JDK
同樣的配置。Java SE 8
中定義的每一個壓縮配置文件的內容大體相同。JDK
和JRE
運行時鏡像以適應模塊並提升性能、安全性和可維護性。URI
方案,用於命名存儲在運行時映像中的模塊,類和資源,而不會泄露映像的內部結構或格式。Java
運行時鏡像中刪除rt.jar
和tools.jar
。JDK
的內部API
都不可訪問,但在全部或大部分功能都支持替換以前,能夠訪問一些關鍵的、普遍使用的內部API
。運行jdeps -jdkinternals
命令以肯定你的的代碼是否使用了內部JDK API
。安全
先來講說模塊系統的兼容性。Java一直是比較保守的,體如今更新上就是良好的兼容性。雖然看了官方對Java
平臺模塊系統的描述好像改動很是大,可是你的舊項目即便不模塊化也是能在新JDK
上運行的。後面會講到沒有模塊化的類包是如何與模塊交互的。框架
既然不模塊化也能好好的運行,那麼爲何要這麼大費周章的折騰代碼呢?ide
第一點,Java 9
前的Java
程序,即便是一個簡單的輸出Hello World
的程序,也必須將整個JDK
、JRE
運行時鏡像打包進去才能運行,這時Java
引覺得傲的數量繁多的類庫反而成了累贅。好比開源的優秀編程庫——Guava
裏有不少很實用的工具類,有時咱們可能只用到了其中一個類而已,卻不得不將整個Guava
類庫打包進咱們的項目。模塊化
第二點,無法定義類是否能被其餘包裏的類引用到。好比咱們編寫了一個工具類,若是但願這個類只能被某些包裏的其餘類引用到,不暴露給其餘包,Java 9
前的Java
程序是作不到這一點的。工具
模塊化一個項目只要在項目的根目錄建立一個module-info.class
文件就能夠了。性能
如圖所示,咱們建立了一個名爲module
的模塊並用關鍵字exports
導出了test
包。若是有其餘模塊導入module
模塊就能夠引用到Main
類了,值得注意的是和test
同級的包和test
內部的包由於沒有被導出,都是不能被引用到的。優化
而引用一個模塊則是用關鍵字requires
:ui
而後就可使用test
包內的類了:
import test.Main; /** * @author Yuicon */ public class Test { public static void main(String[] args) { Main main = new Main(); System.out.println(main); } }
不過在導入前還須要在模塊依賴裏添加要導入的模塊:
java.base
模塊是默認導入的,裏面有咱們經常使用的類庫:
咱們知道模塊化後就能控制那些包能夠被引用到了。不過不止如此,一個模塊的類是不能訪問到其餘模塊裏的類的私有屬性的。聽起來好像是理所固然的,這是由於原先咱們是能夠用反射來訪問到私有屬性的。模塊化後就算反射也不能訪問到了,算是增強了安全性。
不過這樣的話,那些依賴反射來獲取私有屬性的框架和庫就倒黴了。爲了兼容這些框架和庫,咱們能夠在模塊定義里加一個關鍵字open
:
module-info.class open module module { exports test; }
這樣咱們就聲明瞭一個開放的模塊,在模塊的全部軟件包上授予深刻的反射訪問權限(訪問公共和私有API)。
在模塊聲明文件裏一共有五種模塊語句,分別是:
package test.driver; /** * @author Yuicon */ public interface Driver { int getCode(); }
package test; import test.driver.Driver; /** * @author Yuicon */ public class DriverImpl implements Driver { @Override public int getCode() { return 10086; } }
module module { exports test.driver; // 導出包 provides Driver with DriverImpl; // 爲接口Driver提供實現 }
module queue { requires module; // 導入包 opens test; // 開放包的反射權限 uses Driver; // 聲明使用接口 }
package main; import test.driver.Driver; import java.util.ServiceLoader; /** * @author Yuicon */ public class Main { public static void main(String[] args) { // 獲取實現 ServiceLoader<Driver> serviceLoader = ServiceLoader.load(Driver.class); serviceLoader.findFirst().ifPresent(driver -> System.out.println(driver.getCode())); } } 輸出: 10086 Process finished with exit code 0
你能夠建立一個不包含任何代碼的模塊,它收集並從新導出其餘模塊的內容,這樣的模塊稱爲聚合模塊。假設有幾個模塊依賴於五個模塊,你能夠爲這五個模塊建立一個聚合模塊。如今,你的模塊只能依賴於一個模塊——聚合模塊。
爲了方便,Java 9
包含幾個聚合模塊,如java.se
和java.se.ee
。java.se
模塊收集Java SE
的不與Java EE
重疊的部分。java.se.ee
模塊收集組成Java SE
的全部模塊,包括與Java EE
重疊的模塊。