Java8的Optional:如何幹掉空指標?
阿新 • • 發佈:2021-01-04
[toc]
## Optional概述
Optional 是個容器:它可以儲存型別T的value,或者僅僅儲存null。Optional提供很多有用的方法,這樣我們就不用顯式進行空值檢測,很好地解決了空指標異常處理的問題,比如可以使用`isPresent()`方法判斷value是否為null,使用`get()`方法獲取value值等等。
Optional的構造方法是私有的,例項不能new,可以使用靜態方法來建立:
```java
// 1、建立一個包裝物件值為空的Optional物件
Optional optStr = Optional.empty();
// 2、建立包裝物件值非空的Optional物件
Optional optStr1 = Optional.of("optional");
// 3、建立包裝物件值允許為空的Optional物件
Optional optStr2 = Optional.ofNullable(null);
```
## Optional簡單案例
看完Optional的概述,我們用一個簡單的例子說明一下:
下面這段程式碼接收一個User物件,如果user為null,則丟擲異常【這是一個非常常規的避免空指標異常的做法,如果沒有這步,getName會NPE】,否則返回user的name。
```java
public String getName1(User user) {
if (user == null) {
throw new RuntimeException("user不能為null!");
}
return user.getName();
}
```
如果使用Optional,應該怎麼去處理呢?
```java
public String getName2(User user) {
return Optional.ofNullable(user) // 包裝user物件,如果user為null,則返回空的Optional物件
.map(User::getName)
.orElseThrow(() -> new RuntimeException("user不能為null"));// 如果有值則返回,沒有則丟擲異常。
}
```
- Optional使用靜態的`ofNullable`方法將user物件進行包裝,將可能為null的user物件保護起來。
```java
public static Optional ofNullable(T value) {
// empty() 方法 建立一個空的Optional物件, of物件在構造Optional的時候,value如果weinull,會引發NPE
return value == null ? empty() : of(value);
}
```
- orElseThrow方法接收一個Supplier 物件,這裡我們在lambda表示式那節已經說過了,不再贅述,感興趣可以檢視:[Java8的Lambda表示式,你會不?](https://blog.csdn.net/Sky_QiaoBa_Sum/article/details/110789826)
```java
public T orElseThrow(Supplier extends X> exceptionSupplier) throws X {
// 如果有值,直接返回值
if (value != null) {
return value;
} else {
// 丟擲異常,這個異常Supplier介面定義
throw exceptionSupplier.get();
}
}
```
## Optional的主要方法
| 方法 | 描述 |
| ------------- | ------------------------------------------------------------ |
| `empty` | 返回一個空的 Optional 例項 |
| `filter` | 如果值存在並且滿足提供的斷言, 就返回包含該值的 Optional 物件;否則返回一個空的 Optional 物件 |
| `map` | 如果值存在,就對該值執行提供的 mapping 函式呼叫 |
| `flatMap` | 如果值存在,就對該值執行提供的 mapping 函式呼叫,返回一個 Optional 型別的值,否則就返 回一個空的 Optional 物件 |
| `get` | 如果該值存在,將該值用 Optional 封裝返回,否則丟擲一個 NoSuchElementException 異常 |
| `ifPresent` | 如果值存在,就執行使用該值的方法呼叫,否則什麼也不做 |
| `isPresent` | 如果值存在就返回 true,否則返回 false |
| `of` | 將指定值用 Optional 封裝之後返回,如果該值為 null,則丟擲一個 NullPointerException 異常 |
| `ofNullable` | 將指定值用 Optional 封裝之後返回,如果該值為 null,則返回一個空的 Optional 物件 |
| `orElse` | 如果有值則將其返回,否則返回一個預設值 |
| `orElseGet` | 如果有值則將其返回,否則返回一個由指定的 Supplier 介面生成的值 |
| `orElseThrow` | 如果有值則將其返回,否則丟擲一個由指定的 Supplier 介面生成的異常 |
## 參考閱讀
- [Java 8 Optional 類](https://www.runoob.com/java/java8-optional-class.html)
- [【java8新特性 簡述】Optional](https://www.jianshu.com/p/0fd4637a55a6)
- [https://github.com/biezhi/learn-java8/blob/master/java8-optional/README.md](https://github.com/biezhi/learn-java8/blob/master/java8-optional/RE