Java9有哪些新特性?

中興開發者社群發表於2017-11-15

點選上方“中興開發者社群”,關注我們

每天讀一篇一線開發者原創好文640?wx_fmt=png&wxfrom=5&wx_lazy=1

Java有哪些吸引人的新特性?讓我們來共同瞭解....


1. Java 平臺級模組系統


Java 9 的定義功能是一套全新的模組系統。當程式碼庫越來越大,建立複雜,盤根錯節的“義大利麵條式程式碼”的機率呈指數級的增長。這時候就得面對兩個基礎的問題: 很難真正地對程式碼進行封裝, 而系統並沒有對不同部分(也就是 JAR 檔案)之間的依賴關係有個明確的概念。每一個公共類都可以被類路徑之下任何其它的公共類所訪問到, 這樣就會導致無意中使用了並不想被公開訪問的 API。此外,類路徑本身也存在問題: 你怎麼知曉所有需要的 JAR 都已經有了, 或者是不是會有重複的項呢? 模組系統把這倆個問題都給解決了。


模組化的 JAR 檔案都包含一個額外的模組描述器。在這個模組描述器中, 對其它模組的依賴是通過 “requires” 來表示的。另外, “exports” 語句控制著哪些包是可以被其它模組訪問到的。所有不被匯出的包預設都封裝在模組的裡面。如下是一個模組描述器的示例,存在於 “module-info.java” 檔案中:

640?wx_fmt=png&wxfrom=5&wx_lazy=1


我們可以如下展示模組:


640?wx_fmt=png&wxfrom=5&wx_lazy=1


請注意,兩個模組都包含封裝的包,因為它們沒有被匯出(使用橙色盾牌視覺化)。 沒有人會偶然地使用來自這些包中的類。Java 平臺本身也使用自己的模組系統進行了模組化。通過封裝 JDK 的內部類,平臺更安全,持續改進也更容易。


當啟動一個模組化應用時, JVM 會驗證是否所有的模組都能使用,這基於 `requires` 語句——比脆弱的類路徑邁進了一大步。模組允許你更好地強制結構化封裝你的應用並明確依賴。


2. Linking

當你使用具有顯式依賴關係的模組和模組化的 JDK 時,新的可能性出現了。你的應用程式模組現在將宣告其對其他應用程式模組的依賴以及對其所使用的 JDK 模組的依賴。為什麼不使用這些資訊建立一個最小的執行時環境,其中只包含執行應用程式所需的那些模組呢? 這可以通過 Java 9 中的新的 jlink 工具實現。你可以建立針對應用程式進行優化的最小執行時映像而不需要使用完全載入 JDK 安裝版本。


3. JShell: 互動式 Java REPL

許多語言已經具有互動式程式設計環境,Java 現在加入了這個俱樂部。您可以從控制檯啟動 jshell ,並直接啟動輸入和執行 Java 程式碼。 jshell 的即時反饋使它成為探索 API 和嘗試語言特性的好工具。


640?wx_fmt=png


測試一個 Java 正規表示式是一個很好的說明 jshell 如何使您的生活更輕鬆的例子。 互動式 shell 還可以提供良好的教學環境以及提高生產力。在教人們如何編寫 Java 的過程中,不再需要解釋 “public static void main(String [] args)” 這句廢話。


4. 改進的 Javadoc

有時一些小事情可以帶來很大的不同。你是否就像我一樣在一直使用 Google 來查詢正確的 Javadoc 頁面呢? 這不再需要了。Javadoc 現在支援在 API 文件中的進行搜尋。另外,Javadoc 的輸出現在符合相容 HTML5 標準。此外,你會注意到,每個 Javadoc 頁面都包含有關 JDK 模組類或介面來源的資訊。


640?wx_fmt=png


5. 集合工廠方法

通常,您希望在程式碼中建立一個集合(例如,List 或 Set ),並直接用一些元素填充它。 例項化集合,幾個 “add” 呼叫,使得程式碼重複。 Java 9,新增了幾種集合工廠方法:


640?wx_fmt=png


除了更短和更好閱讀之外,這些方法也可以避免您選擇特定的集合實現。 事實上,從工廠方法返回已放入數個元素的集合實現是高度優化的。這是可能的,因為它們是不可變的:在建立後,繼續新增元素到這些集合會導致 “UnsupportedOperationException” 。



6. 改進的 Stream API

長期以來,Stream API 都是 Java 標準庫最好的改進之一。通過這套 API 可以在集合上建立用於轉換的申明管道。在 Java 9 中它會變得更好。Stream 介面中新增了 4 個新的方法:dropWhile, takeWhile, ofNullable。還有個 iterate 方法的新過載方法,可以讓你提供一個 Predicate (判斷條件)來指定什麼時候結束迭代:


640?wx_fmt=png


第二個引數是一個 Lambda,它會在當前 IntStream 中的元素到達 100 的時候返回 true。因此這個簡單的示例是向控制檯列印 1 到 99。


除了對 Stream 本身的擴充套件,Optional 和 Stream 之間的結合也得到了改進。現在可以通過 Optional 的新方法 `stram` 將一個 Optional 物件轉換為一個(可能是空的) Stream 物件:


640?wx_fmt=png


在組合複雜的 Stream 管道時,將 Optional 轉換為 Stream 非常有用。


7. 私有介面方法

Java 8 為我們帶來了介面的預設方法。 介面現在也可以包含行為,而不僅僅是方法簽名。 但是,如果在介面上有幾個預設方法,程式碼幾乎相同,會發生什麼情況? 通常,您將重構這些方法,呼叫一個可複用的私有方法。 但預設方法不能是私有的。 將複用程式碼建立為一個預設方法不是一個解決方案,因為該輔助方法會成為公共API的一部分。 使用 Java 9,您可以向介面新增私有輔助方法來解決此問題:


640?wx_fmt=png


如果您使用預設方法開發 API ,那麼私有介面方法可能有助於構建其實現。


8. HTTP/2

Java 9 中有新的方式來處理 HTTP 呼叫。這個遲到的特性用於代替老舊的 `HttpURLConnection` API,並提供對 WebSocket 和 HTTP/2 的支援。注意:新的 HttpClient API 在 Java 9 中以所謂的孵化器模組交付。也就是說,這套 API 不能保證 100% 完成。不過你可以在 Java 9 中開始使用這套 API:

HttpClient client = HttpClient.newHttpClient();HttpRequest req =   HttpRequest.newBuilder(URI.create("http://www.google.com"))              .header("User-Agent","Java")              .GET()              .build();HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandler.asString


除了這個簡單的請求/響應模型之外,HttpClient 還提供了新的 API 來處理 HTTP/2 的特性,比如流和服務端推送。


9. 多版本相容 JAR

我們最後要來著重介紹的這個特性對於庫的維護者而言是個特別好的訊息。當一個新版本的 Java 出現的時候,你的庫使用者要花費數年時間才會切換到這個新的版本。這就意味著庫得去向後相容你想要支援的最老的 Java 版本 (許多情況下就是 Java 6 或者 7)。這實際上意味著未來的很長一段時間,你都不能在庫中運用 Java 9 所提供的新特性。幸運的是,多版本相容 JAR 功能能讓你建立僅在特定版本的 Java 環境中執行庫程式時選擇使用的 class 版本:


640?wx_fmt=png


在上述場景中, multirelease.jar 可以在 Java 9 中使用, 不過 Helper 這個類使用的不是頂層的multirelease.Helper 這個 class, 而是處在“META-INF/versions/9”下面的這個。這是特別為 Java 9 準備的 class 版本,可以運用 Java 9 所提供的特性和庫。同時,在早期的 Java 諸版本中使用這個 JAR 也是能執行的,因為較老版本的 Java 只會看到頂層的這個 Helper 類。


如你所見,Java 9 提供了一大堆或大或小的功能特性,你準備好了麼?

640?wx_fmt=jpeg

相關文章