JAVA9新特性(一)

Bug如風常伴吾身發表於2018-01-29

JAVA9新特性(一)

JAVA9於北京時間2017年9月22日(當地9.21)正式釋出,可以在官網上下載到最新的jdk9,但是目前只支援64位作業系統。

所有特性目錄:http://blog.csdn.net/diehuang3426/article/details/79233952
知乎有個問題描述的也不錯:https://www.zhihu.com/question/65683103/answer/233904009

Java平臺級模組系統(Java Platform Module System)

(PS:此頁全是Java平臺級模板系統,想看其他的,請看JAVA9新特性(二))

什麼是Java Module(模組)

模組是程式碼和資料集合。 它可以包含Java程式碼和原生程式碼。 Java程式碼被組織為一組包含諸如類,介面,列舉和註解等型別的類。 資料可以包括諸如影象檔案和配置檔案的資源。一個模組不僅僅是一個包的容器。 除了其名稱,模組定義包含以下內容:

  • 所需的其他模組(或依賴於)的列表
  • 匯出的軟體包列表(其公共API),其他模組可以使用
  • 開放的軟體包(其整個API,公共和私有)到其他反射訪問模組的列表
  • 使用的服務列表(或使用java.util.ServiceLoader類發現和載入)
  • 提供的服務的實現列表

在使用這些模組時,可以使用這些方面中的一個或多個。
這裡寫圖片描述
Java SE 9平臺規範將平臺劃分為稱為平臺模組的一組模組。 Java SE 9平臺的實現可能包含一些或所有平臺模組,從而提供可擴充套件的Java執行時。 標準模組的名字是以Java 為字首。Java SE標準模組的示例有java.base,java.sql,java.xml和java.logging。 支援標準平臺模組中的API,供開發人員使用。

JavaFX不是Java SE 9平臺規範的一部分。 但是,在安裝JDK/JRE時,會安裝與JavaFX相關的模組。 JavaFX模組名稱以javafx為字首。 JavaFX模組的示例是javafx.base,javafx.controls,javafx.fxml,javafx.graphics和javafx.web。

作為Java SE 9平臺的一部分的java.base模組是原始模組。 它不依賴於任何其他模組。 模組系統只知道java.base模組。 它通過模組中指定的依賴關係發現所有其他模組。 java.base模組匯出核心Java SE軟體包,如java.lang,java.io,java.math,java.text,java.time,java.util等。

在JDK 9中,如果一個模組依賴於另一個模組,並且執行應用程式時第二個模組丟失,則在啟動時將會收到一個錯誤,而不是應用程式執行後的某個時間。 這是一個可靠的基礎配置。

模組的目標

模組系統的開發具有三大目標:可靠的配置,強封裝,模組化JDK/JRE。這些目標是解決Java 9之前開發和部署Java應用程式所面臨的問題。

可靠的配置解決了用於查詢型別的容易出錯的類路徑機制的問題。 模組必須宣告對其他模組的顯式依賴。 模組系統驗證應用程式開發的所有階段的依賴關係 —— 編譯時,連結時和執行時。 假設一個模組宣告對另一個模組的依賴,並且第二個模組在啟動時丟失。 JVM檢測到依賴關係丟失,並在啟動時失敗。 在Java 9之前,當使用缺少的型別時,這樣的應用程式會生成執行時錯誤(不是在啟動時)。

強大的封裝解決了類路徑上跨JAR的公共型別的可訪問性問題。 模組必須明確宣告其中哪些公共型別可以被其他模組訪問。 除非這些模組明確地使其公共型別可訪問,否則模組不能訪問另一個模組中的公共型別。 Java 9中的公共型別並不意味著程式的所有部分都可以訪問它。 模組系統增加了更精細的可訪問性控制。

模組化JDK/JRE使得開發和維護更加簡單。例如JRE有一個超級大rt.jar(例如,Java 8的rt.jar中有65M),執行一個hello world,你也需要一個數百兆的JRE環境,如果在J2EE環境,情況將變得複雜無比。把龐大冗餘的Java鋸成一個個的Module,改進了Java SE 平臺,使其可以適應不同大小的計算裝置,並改進其安全性,可維護性,提高效能。
這裡寫圖片描述

模組語法

這裡寫圖片描述
< module-statement >是一個模組語句。 模組宣告中可以包含零個或多個模組語句。 如果它存在,它可以是五種型別的語句之一:
匯出語句(exports statement);
開放語句(opens statement);
需要語句(requires statement);
使用語句(uses statement);
提供語句(provides statement)。

模組命名

模組名稱可以是Java限定識別符號。 合法識別符號是一個或多個由點分隔的識別符號,例如policy,com.jdojo.common和com.jdojo.util。 如果模組名稱中的任何部分不是有效的Java識別符號,則會發生編譯時錯誤。 例如,com.jdojo.common.1.0不是有效的模組名稱,因為名稱中的1和0不是有效的Java識別符號。與包命名約定類似,使用反向域名模式為模組提供唯一的名稱。 使用這個慣例,名為com.jdojo.common的最簡單的模組可以宣告如下:
這裡寫圖片描述
模組名稱不會隱藏具有相同名稱的變數,型別和包。 因此,可以擁有一個模組以及具有相同名稱的變數,型別或包。 他們使用的上下文將區分哪個名稱是指什麼樣的實體。
在JDK 9中, open, module, requires, transitive, exports, opens, to, uses, provides 和 with是受限關鍵字。只有當具體位置出現在模組宣告中時,它們才具有特殊意義。 可以將它們用作程式中其他地方的識別符號。 例如,以下模組宣告是有效的,即使它不使用直觀的模組名稱:
這裡寫圖片描述
第一個模組字被解釋為一個關鍵字,第二個是一個模組名稱。
你可以在程式中的任何地方宣告一個名為module的變數:
這裡寫圖片描述

exports和requires

匯出語句將模組的指定包匯出到所有模組或編譯時和執行時的命名模組列表。 它的兩種形式如下:
這裡寫圖片描述
這裡寫圖片描述
需要(require)語句宣告當前模組與另一個模組的依賴關係。 一個名為M的模組中的“需要N”語句表示模組M取決於(或讀取)模組N。語句有以下形式:
這裡寫圖片描述
require語句中的靜態修飾符表示在編譯時的依賴是強制的,但在執行時是可選的。requires static N語句意味著模組M取決於模組N,模組N必須在編譯時出現才能編譯模組M,而在執行時存在模組N是可選的。require語句中的transitive修飾符會導致依賴於當前模組的其他模組具有隱式依賴性。假設有三個模組P,Q和R,假設模組Q包含requires transitive R語句,如果如果模組P包含包含requires Q語句,這意味著模組P隱含地取決於模組R。
這裡寫圖片描述
下圖描述了兩個名為policy和claim的模組之間的依賴關係。 policy模組包含兩個名為pkg1和pkg2的包,它匯出包pkg1,該包使用虛線邊界顯示,以將其與未匯出的包pkg2區分開來。 claim模組包含兩個件包pkg3和pkg4,它不匯出包。 它宣告瞭對policy模組的依賴。
這裡寫圖片描述
這裡寫圖片描述

open

如果你的模組依賴於另一個模組,則該模組宣告要求知道模組名稱。一些Java框架和工具(Spring,Hibernate…)在很大程度上依賴於反射來在執行時訪問未匯出的模組的程式碼
當模組匯出軟體包時,依賴於第一個模組的其他模組只能訪問匯出的軟體包中的公共API。 在執行時,在模組的所有軟體包上授予深入的反射訪問許可權(訪問公共和私有API),可以宣告一個開放的模組。

這裡寫圖片描述
這裡寫圖片描述
開放語句允許對所有模組的反射訪問指定的包或執行時指定的模組列表。 其他模組可以使用反射訪問指定包中的所有型別以及這些型別的所有成員(私有和公共)。 開放語句如同exports形式
這裡寫圖片描述
匯出語句允許僅在編譯時和執行時訪問指定包的公共API,而開啟語句允許在執行時使用反射訪問指定包中的所有型別的公共和私有成員。

uses和provides

Java允許使用服務提供者和服務使用者分離的服務提供者機制。 JDK 9允許使用語句(uses statement)和提供語句(provides statement)實現其服務。
使用語句可以指定服務介面的名字,當前模組就會發現它,使用 java.util.ServiceLoader類進行載入。格式如下:
這裡寫圖片描述
這裡寫圖片描述
com.jdojo.PrimeChecker是一個服務介面,其實現類將由其他模組提供。 模組M將使用java.util.ServiceLoader類來發現和載入此介面的實現。
提供語句指定服務介面的一個或多個服務提供程式實現類。 它採取以下形式:
這裡寫圖片描述
相同的模組可以提供服務實現,可以發現和載入服務。 模組還可以發現和載入一種服務,併為另一種服務提供實現。
這裡寫圖片描述

模組的訪問許可權

模組之間的關係被稱作readability(可讀性),代表一個模組是否可以找到這個模組檔案,並且讀入系統中(注意:並非代表可以訪問其中的型別)。在實際的程式碼,一個型別對於另外一個型別的呼叫,我們稱之為可訪問性(Accessible),這意味著可以使用這個型別; 可訪問性的前提是可讀性,換句話說,先有模組可讀,然後才能再進一步檢測可訪問性(安全)。
這裡寫圖片描述
這裡寫圖片描述

類載入器查詢類方式改變

在這三個級別的Loader下面有一個統一Module 管理,用於控制和管理模組間的依賴關係,可讀性,可訪問性等。ClassLoader在Java 9中的類裝載邏輯和之前一樣,但是,通過模組管理系統,ClassLoader.FindClass的能力,將被限制在readable&accessible的條件下,而不是之前的簡單的Public條件。
這裡寫圖片描述

PS:此文章為網路糅合編寫,侵刪。

相關文章