什麼?Java9這些史詩級更新你都不知道?Java9特性一文打盡!
阿新 • • 發佈:2020-08-20
![](https://cdn.jsdelivr.net/gh/wmyskxz/BlogImage01/什麼?Java9的這些史詩級更新你都不知道?Java9版本特性一文打盡!/image-20200820103424921.png)
- **「MoreThanJava」** 宣揚的是 **「學習,不止 CODE」**,本系列 Java 基礎教程是自己在結合各方面的知識之後,對 Java 基礎的一個總回顧,旨在 **「幫助新朋友快速高質量的學習」**。
- 當然 **不論新老朋友** 我相信您都可以 **從中獲益**。如果覺得 **「不錯」** 的朋友,歡迎 **「關注 + 留言 + 分享」**,文末有完整的獲取連結,您的支援是我前進的最大的動力!
# 特性總覽
以下是 Java 9 中的引入的部分新特性。關於 Java 9 新特性更詳細的介紹可參考[這裡](https://openjdk.java.net/projects/jdk9/)。
- REPL(JShell)
- 不可變集合的工廠方法
- 模組系統
- 介面支援私有化
- 鑽石操作符升級
- Optional 改進
- Stream API 改進
- 反應式流(Reactive Streams)
- 程序 API
- 升級的 Try-With-Resources
- HTTP / 2
- 多版本相容 Jar 包
- 其他
- 改進應用安全效能
- 統一 JVM 日誌
- G1 設為預設垃圾回收器
- String 底層儲存結構更改
- CompletableFuture API 改進
- I/O 流新特性
- JavaScript 引擎 Nashorn 改進
- 識別符號增加限制
- 改進的 Javadoc
- 改進的 @Deprectaed 註解
- 多解析度影象 API
- 變數控制代碼
- 改進方法控制代碼(Method Handle)
- 提前編譯 AOT
# 一. Java 9 REPL(JShell)
## 什麼是 REPL 以及為什麼引入
**REPL**,即 **Read-Evaluate-Print-Loop** 的簡稱。由於 [Scala](https://zh.wikipedia.org/zh-my/Scala) 語言的特性和優勢在小型應用程式到大型應用程式市場大受追捧,於是引來 Oracle 的關注,並嘗試將大多數 Scala 功能整合到 Java 中。這在 Java 8 中已經完成一部分,比如 Lambda 表示式。
Scala 的最佳功能之一就是 REPL,這是一個命令列介面和 Scala 直譯器,用於執行 Scala 程式。由於並不需要開啟額外的 IDE *(就是一個命令列)*,它在減少學習曲線和簡化執行測試程式碼方面有獨特的優勢。
於是在 Java 9 中引入了 Java REPL,也稱為 `JShell`。
## JShell 基礎
開啟命令提示符,確保您具有 Java 9 或更高版本,鍵入 `jshell`,然後我們就可以開心的使用了。
**下面是簡單示範:**
```bash
wmyskxz:~ wmyskxz$ jshell
| Welcome to JShell -- Version 9
| For an introduction type: /help intro
jshell>
jshell> System.out.println("Hello World");
Hello World
jshell> String str = "Hello JShell!"
str ==> "Hello JShell!"
jshell> str
str ==> "Hello JShell!"
jshell> System.out.println(str)
Hello JShell!
jshell> int counter = 0
counter ==> 0
jshell> counter++
$6 ==> 0
jshell> counter
counter ==> 1
jshell> counter+5
$8 ==> 6
```
**也可以在 Java Shell 中定義和執行類方法:**
```bash
jshell> class Hello {
...> public static void sayHello() {
...> System.out.print("Hello");
...> }
...> }
| created class Hello
jshell> Hello.sayHello()
Hello
jshell>
```
## Java REPL - 幫助和退出
要獲得 `jshell` 工具的幫助部分,請使用`/help`命令。要從 `jshell` 退出,請使用 `/exit` 命令 *(或者直接使用 `Ctrl + D` 命令退出)*。
```bash
jshell> /help
| Type a Java language expression, statement, or declaration.
| Or type one of the following commands:
| /list [|-all|-start]
| list the source you have typed
| /edit
...
jshell> /exit
| Goodbye
wmyskxz:~ wmyskxz$
```
# 二. 不可變集合的工廠方法
Java 9 中增加了一些便捷的工廠方法用於建立 **不可變** List、Set、Map 以及 Map.Entry 物件。
在 Java SE 8 和更早的版本中,如果我們要建立一個空的 **不可變** 或 **不可修改** 的列表,需要藉助 `Collections` 類的 `unmodifiableList()` 方法才可以:
```java
List list = new ArrayList<>();
list.add("公眾號");
list.add("我沒有三顆心臟");
list.add("關注走起來");
List immutableList = Collections.unmodifiableList(list);
```
可以看到,為了建立一個非空的不可變列表,我們需要經歷很多繁瑣和冗長的步驟。為了克服這一點,Java 9 在 `List` 介面中引入了以下有用的過載方法:
```java
static List of(E e1)
static List of(E e1,E e2)
static List of(E e1,E e2,E e3)
static List of(E e1,E e2,E e3,E e4)
static List of(E e1,E e2,E e3,E e4,E e5)
static List of(E e1,E e2,E e3,E e4,E e5,E e6)
static List of(E e1,E e2,E e3,E e4,E e5,E e6,E e7)
static List of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8)
static List of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8,E e9)
static List of(E e1,E e2,E e3,E e4,E e5,E e6,E e7,E e8,E e9,E e10)
```
以及可變引數數目的方法:
```java
static List of(E... elements)
```
可以看到 Java 9 前後的對比:
```java
// Java 9 之前
List list = new ArrayList<>();
list.add("公眾號");
list.add("我沒有三顆心臟");
list.add("關注走起來");
List unmodifiableList = Collections.unmodifiableList(list);
// 或者使用 {{}} 的形式
List list = new ArrayList<>() {{
add("公眾號");
add("我沒有三顆心臟");
add("關注走起來");
}};
List unmodifiableList = Collections.unmodifiableList(list);
// Java 9 便捷的工廠方法
List unmodifiableList = List.of("公眾號", "我沒有三顆心臟", "關注走起來");
```
*(ps: Set、Map 類似,Map 有兩組方法:`of()` 和 `ofEntries()` 分別用於建立 Immutable Map 物件和 Immutable Map.Entry 物件)*
另外 Java 9 可以直接輸出集合的內容,在此之前必須遍歷集合才能全部獲取裡面的元素,這是一個很大的改進。
## 不可變集合的特徵
不可變即不可修改。它們通常具有以下幾個特徵:
1、我們無法新增、修改和刪除其元素;
2、如果嘗試對它們執行新增/刪除/更新操作,將會得到 `UnsupportedOperationException` 異常,如下所示:
```bash
jshell> immutableList.add("Test")
| java.lang.UnsupportedOperationException thrown:
| at ImmutableCollections.uoe (ImmutableCollections.java:68)
| at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:74)
| at (#2:1)
```
3、不可變集合不允許 null 元素;
4、如果嘗試使用 null 元素建立,則會報出 `NullPointerException` 異常,如下所示:
```bash
jshell> List>String> immutableList = List.of("公眾號","我沒有三顆心臟","關注走起來", null)
| java.lang.NullPointerException thrown:
| at Objects.requireNonNull (Objects.java:221)
| at ImmutableCollections$ListN. (ImmutableCollections.java:179)
| at List.of (List.java:859)
| at (#4:1)
```
5、如果嘗試新增 null 元素,則會得到 `UnsupportedOperationException` 異常,如下所示:
```bash
jshell> immutableList.add(null)
| java.lang.UnsupportedOperationException thrown:
| at ImmutableCollections.uoe (ImmutableCollections.java:68)
| at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:74)
| at (#3:1)
```
6、如果所有元素都是可序列化的,那麼集合是可以序列化的;
# 三. 模組系統
Java 模組系統是 Oracle 在 Java 9 引入的全新概念。最初,它作為 Java SE 7 Release 的一部分啟動了該專案,但是由於進行了很大的更改,它被推遲到了 Java SE 8,然後又被推遲了。最終隨著 2017 年 9 月釋出的 Java SE 9 一起釋出。
## 為什麼需要模組系統?
當代碼庫變得更大時,建立複雜、糾結的 “義大利麵條程式碼” 的機率成倍增加。在 Java 8 或更早版本交付 Java 應用時存在幾個基本問題:
1. **難以真正封裝程式碼**,並且在系統的不同部分(JAR 檔案)之間沒有顯式依賴關係的概念。每個公共類都可以由 classpath 上的任何其他公共類訪問,從而導致無意中使用了本不應該是公共 API 的類。
2. 再者,類路徑本身是有問題的:**您如何知道是否所有必需的 JAR 都存在,或者是否存在重複的條目?**
3. 另外,**JDK 太大了**,`rt.jar` *(`rt.jar` 就是 Java 基礎類庫——也就是 Java Doc 裡面看到的所有類的 class 檔案)*等 JAR 檔案甚至無法在小型裝置和應用程式中使用:因此我們的應用程式和裝置無法支援更好的效能——打包之後的應用程式太大了——也很難測試和維護應用程式。
模組系統解決了這幾個問題。
## 什麼是 Java 9 模組系統?
模組就是程式碼、資料和一些資源的自描述集合。它是一組與程式碼、資料和資源相關的包。
每個模組僅包含一組相關的程式碼和資料,以支援單一職責原則(SRP)。
![](https://cdn.jsdelivr.net/gh/wmyskxz/BlogImage01/什麼?Java9的這些史詩級更新你都不知道?Java9版本特性一文打盡!/image-20200820062506819.png)
Java 9 模組系統的主要目標就是支援 **Java 模組化程式設計**。*(我們將在下面