---
# System prepended metadata

title: '[Java 8] Optional 的各種用法'
tags: [Java 8, Java]

---

# [Java 8] Optional 的各種用法
###### tags: `Java` `Java 8`

Java8 新加入的類，是一個 `value-based class` ，這樣的 class 的實例有以下的特色：

* 本身是 final 和 immutable (內含物可能是 mutable)
* 可以用 `equals` 判斷是否相同，但無法用 `==` 來判斷是否相同
* 沒有 accessible constructor ，但是有 factory methods，但這些方法不會承諾返回值的身份
* 不能使用像是 `==` , hash code 或是 lock
* 如果 `equals()` 判斷是相等，那就可以交換使用

另外，作為 class field 的話，如下：
```=java!
public class Student {

    private Optional<String> name;
    // ...
}
```
因為 Optional 是設計用來 method 的回傳型態，因此它並沒有實作序列化`Serializable` 介面，在特定狀況下需要物件序列化時將會出現問題。

## `orElse()`、`orElseGet()` 的差異
若內容物為null時，可用 `.orElse()`、`.orElseGet()` 來回傳其它結果。
- `orElse()`
    回傳值為任意傳入的值
- `orElseGet()`
    回傳值為指定的值，類似給予預設值。也因此相較於 `.orElse()` ，`.orElseGet()` 可以在給予指定的值時做另外的處理

若希望能在null時報錯提示，也可以使用 `orElseThrow()` 來回傳指定的 Exception
```=java!
Optional<Something> something = myRepo.findById(id)
    .orElseThrow(() -> new NotFoundException(id));
```

## `of()`、`ofNullable()` 的差異
若該變數絕對不可為null時，使用 `.of()` ;反之，若有可能為null，則使用 `.ofNullable()` 

```=java!
//如果參數是null，ofNullable會回傳空的物件(Optional[])而不報錯
Optional<Integer> roomNumber = Optional.ofNullable(employee

Optional<Integer> roomNumber = Optional.ofNullable(employee)
                                       .map(e -> e.getCompany())
```


參考來源：
[Optional (Java SE 10 & JDK 10 )](https://docs.oracle.com/javase/10/docs/api/java/util/Optional.html)
[[Java] Optional 用法](https://shoujhengduan.medium.com/java-optional-%E7%94%A8%E6%B3%95-c861b4733a68)
[多此一舉! 不要這樣用 Java 8 Optional](https://ithelp.ithome.com.tw/articles/10310210)