Java 9 的模塊(Module)系統(tǒng)

Java 的模塊在Java 9中正式實裝杈帐,一直沒時間來研究一下這個東西僵控,今天就和大家一起學習一下這個功能。

Java模塊解決了什么問題

最近很多同學問我图柏,胖哥序六,該怎么學習?該學習什么蚤吹?這里胖哥也穿插說一下例诀。不管學東西,一定要先搞清楚學了有什么用裁着,是學了馬上就能用上還是以后有用繁涂。我覺得在時間有限的情況下,一定要學當前立馬有用的東西二驰。接下來咱們就一起來看看Java模塊到底有啥用扔罪。

我覺得模塊化最大的意義就是按照功能把代碼邏輯分割開來,就像你干前端桶雀,我寫后端矿酵,他做測試,把整體大概念拆成小概念矗积,用的時候自由組合全肮,按需引用。事實上確實有這方面的作用棘捣,但是不僅僅就這么多辜腺。

簡化類庫

JDK類庫目前太臃腫了,在一些微型設(shè)備上可能用不到全部的功能乍恐,在目前的情況下卻不得不引用全部的類庫哪自。Java 9引入模塊功能后,JDK禁熏、JRE、甚至是JAR都可以把用不到的類庫排除掉邑彪,大大降低了依賴庫的規(guī)模瞧毙。

真正的訪問隔離

在之前只要類是public的,可以直接在整個依賴可傳遞的范圍內(nèi)訪問它寄症。但是很多時候我們需要在某個范圍去限制一些類的訪問宙彪,讓這些類具有一些封閉性。在引入模塊后有巧,我們就可以做到這些释漆,把一些我們不想暴露的內(nèi)部實現(xiàn)細節(jié)安全地隱藏起來。

什么是模塊篮迎?

Java 9 引入的模塊是在Java包(package)的基礎(chǔ)上又引入的一個新的抽象層男图∈咀耍基于package這一點很重要,這里需要強調(diào)一下逊笆。

模塊的結(jié)構(gòu)

Java 模塊可以由一個或者多個在一起的 Java 包組成栈戳。結(jié)構(gòu)可以參考這個圖:

Java Modules

創(chuàng)建模塊

創(chuàng)建模塊需要如下幾個步驟:

  • 創(chuàng)建一個文件夾,通常是一個包名难裆,例如cn.felord.module子檀。
  • 然后在cn.felord.module下創(chuàng)建一個module-info.java文件,這個文件被稱為模塊描述符文件乃戈。
  • 模塊描述符文件的同級別創(chuàng)建Java包褂痰。
  • 最后在創(chuàng)建的包下編寫你的Java類文件即可。

創(chuàng)建模塊規(guī)則

創(chuàng)建模塊也必須遵守下面的規(guī)則:

  • 模塊名稱必須是唯一的症虑。

  • 模塊描述符文件module-info.java 必須有缩歪。

  • 包名稱必須是唯一的。即使在不同的模塊中侦讨,我們也不能有相同的包名驶冒。

  • 每個模塊將創(chuàng)建一個 jar 文件。對于多個 jar韵卤,我們需要創(chuàng)建單獨的模塊骗污。

  • 一個項目可以由多個模塊組成。

模塊類型

模塊同樣還具有類型沈条,一共有四種需忿。

系統(tǒng)模塊

來自 JDK 和 JRE 的模塊±酰可以使用 java --list-modules 列出屋厘,這里列出了一部分:

? .\java.exe --list-modules
java.base@17
java.compiler@17
java.datatransfer@17
java.desktop@17
java.instrument@17
java.logging@17
java.management@17
java.management.rmi@17
# 省略……

應(yīng)用程序模塊

在應(yīng)用程序中創(chuàng)建以實現(xiàn)功能的所有模塊,日常開發(fā)如果涉及到模塊應(yīng)該屬于這一類月而。

自動模塊

現(xiàn)有的 jar 文件汗洒,感覺像兼容舊的類庫。它們其實不是模塊父款。當我們將非模塊 jar 添加到模塊路徑時溢谤,會創(chuàng)建具有 jar 名稱的模塊。該模塊有以下特性:

  • 默認導出所有包憨攒。
  • 默認情況下可以訪問所有其他模塊的類世杀。

未命名模塊

添加到類路徑中的 jar 和類。當我們將 jar 或類添加到類路徑時肝集,所有這些類都會添加到未命名的模塊中

  • 只導出到其他未命名的模塊和自動模塊瞻坝。這意味著,應(yīng)用程序模塊無法訪問這些類杏瞻。
  • 它可以訪問所有模塊的類所刀。

模塊描述符文件

一個模塊只有一個module-info.java衙荐,而且它是有格式要求的,我們來了解一下勉痴。

聲明模塊

我們只需要在module-info.java這樣做就能聲明一個名稱為cn.felord的模塊:

module cn.felord {
}

模塊名稱應(yīng)該是兩個單詞以上赫模,并用英文句號.隔開,上面是一個空模塊蒸矛。

導出包

默認情況下瀑罗,模塊里下所有包都是私有的,即使被外部依賴也無法訪問雏掠,一個模塊之內(nèi)的包還遵循之前的規(guī)則不受模塊影響斩祭。我們可以使用 export 關(guān)鍵字公開特定的包,就像這樣:

module cn.felord {
    exports cn.felord.pkg;
    exports cn.felord.util;
}

請注意cn.felord.pkgexports cn.felord.util不能是空包乡话,導出的包必須聲明Java對象摧玫。

不能導出具體的Java類。

定向?qū)С霭?/h4>

還有一種是定向?qū)С霭笄啵摪鼉H僅向某模塊公開诬像。就像什么特供酒、特供煙一樣闸婴。它的語法是:

exports <包名> to <目標模塊1>,<目標模塊2>,<目標模塊3>,...

我們把上面的cn.felord.util定向?qū)С鼋ocom.xxx:

module cn.felord {
    exports cn.felord.pkg to com.xxx,com.ooo;
    exports cn.felord.util to com.xxx;
}

在上述情況下坏挠,所有模塊都可以訪問 cn.felord.pkg,但只有com.xxx模塊能訪問 cn.felord.util邪乍。

定向?qū)О淖饔糜蚴?strong>模塊降狠。

依賴

如果一個模塊要訪問從其它模塊導出的包,則該模塊必須使用requires關(guān)鍵字導入要訪問的包所在的模塊庇楞。就像上面榜配,雖然cn.felord模塊向com.ooo開放了cn.felord.pkg包, 即使com.ooo依賴了cn.felord也不能直接使用該包下面的類吕晌,需要這樣做:

module com.ooo {
    exports com.ooo.pkg;
    // 注釋掉 Pkg就變紅了 cn.felord.util下面的類無法使用
    requires cn.felord;
}

requires的作用域是模塊蛋褥。

靜態(tài)依賴

有時我們只在編譯時需要一些模塊,它們在運行時是可選的睛驳。例如壁拉,測試或代碼生成庫。這就需要用到靜態(tài)導入了柏靶,關(guān)鍵字是requires static,例如:

module com.xxx {
       // 移除pom 依賴編譯不了
    requires static cn.felord;
}

在此示例中,cn.felord 在編譯時是必需的溃论,但在運行時是可選的屎蜓,有點類似Maven中的<scope>compile</scope>

依賴傳遞

這看起來越來越像Maven了钥勋!a模塊依賴b模塊炬转,b模塊依賴c模塊辆苔,如果a模塊想用c模塊公開的包的話,按照前面的規(guī)則需要再requires模塊c《笈現(xiàn)在借助于requires transitive就可以這樣干驻啤,因為b承上啟下,我們可以這樣:

module b {
    exports b.pkg;
    // 開啟依賴傳遞
    requires transitive  c; 
}

module c {
   exports c.pkg
}

module a {
   requires b; 
}

所有依賴b的模塊將自動依賴c導出的包荐吵,export to定向?qū)С龅陌鼉?yōu)先級最高骑冗。

使用服務(wù)

使用 uses 關(guān)鍵字,我們可以指定我們的模塊需要或使用某些服務(wù)先煎。這個服務(wù)通常是一個接口或抽象類贼涩。它不應(yīng)該是一個實現(xiàn)類。

module com.xxx {
    requires com.ooo;
    // 移除pom 依賴編譯不了
    requires static cn.felord;
    uses com.ooo.pkg.Read;
}

uses只能從模塊自己的包中或者requires薯蝎、requires static以及requires transitive傳遞過來的接口或者抽象類遥倦。

uses用于指定所需要的服務(wù)類或者接口。

給予服務(wù)

我們可以通過provides ... with ...語法占锯,在模塊中聲明一些服務(wù)的實現(xiàn)供其它模塊(通過uses)使用袒哥。

開放反射

反射 API 的 Java 9 封裝和安全性得到了改進。使用反射消略,我們甚至可以訪問對象的私有成員堡称。

從 java 9 開始,默認情況下不打開疑俭。我們可以明確地通過open授予其它模塊反射權(quán)限粮呢。

open com.xxx{
}

在這種情況下,com.xxx 模塊的所有包都可以使用反射訪問钞艇。

opens

我們不想全部開放反射訪問的話還可以使用opens關(guān)鍵字來指定反射可以訪問的包:

module com.xxx{
  opens com.xxx.reflect;
}

opens … to

當然我們還可以將特定的包開放給指定的模塊來反射訪問:

module com.xxx{
  opens com.xxx.reflect to com.ooo;
}

com.xxx模塊的com.xxx.reflect包將開放給com.ooo模塊來反射訪問啄寡。

總結(jié)

模塊的東西主要是理解,實際運用主要用來系統(tǒng)瘦身哩照、依賴jar級別的隔離挺物。這個自己用Java 9 以上版本建一個多模塊的Maven或者Gradle項目,按照上面實驗一下就明白了飘弧。

關(guān)注公眾號:碼農(nóng)小胖哥识藤,獲取更多資訊

個人博客:https://felord.cn

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市次伶,隨后出現(xiàn)的幾起案子痴昧,更是在濱河造成了極大的恐慌,老刑警劉巖冠王,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赶撰,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機豪娜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門餐胀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人瘤载,你說我怎么就攤上這事否灾。” “怎么了鸣奔?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵墨技,是天一觀的道長。 經(jīng)常有香客問我溃蔫,道長健提,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任伟叛,我火速辦了婚禮私痹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘统刮。我一直安慰自己紊遵,他們只是感情好,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布侥蒙。 她就那樣靜靜地躺著暗膜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鞭衩。 梳的紋絲不亂的頭發(fā)上学搜,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音论衍,去河邊找鬼瑞佩。 笑死,一個胖子當著我的面吹牛坯台,可吹牛的內(nèi)容都是我干的炬丸。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼蜒蕾,長吁一口氣:“原來是場噩夢啊……” “哼稠炬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咪啡,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤首启,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后撤摸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毅桃,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了冕象。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡渐扮,死狀恐怖论悴,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情墓律,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布察纯,位于F島的核電站,受9級特大地震影響针肥,放射性物質(zhì)發(fā)生泄漏饼记。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一慰枕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧博肋,春花似錦、人聲如沸匪凡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽术奖。三九已至礁遵,卻和暖如春采记,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背唧龄。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留讽挟,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓耽梅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親诅迷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容