Optional型でのnullの扱い

## Optionalって？
Optionalとは、nullかもしれないことを注意するクラスだよ。
大抵はメソッドの戻り値がnullかもしれない場合に利用しするよ。
Optional型で返すと、nullの場合はヌルポによる意図しないエラーをなくすことができるし、nullかもしれない値に何か処理を行いたい場合にも利用できるよ。
実際に使ってみよう。

## 具体例
### もしOptional型を使わなかったら...
Javaではよくヌルポが発生するので、nullかどうかのチェックをする必要があるよ。
こんな感じに。
```Java
public class Main {
    public static void main(String[] args) {
    String val = "Hello!";
        if (val != null) {
            System.out.print(val + "Java");
        }
    }
}
```
面倒なnullチェックをなくせるOptional型を使ってみよう。

### 基本的な使い方
Optional型で戻り値がnullの可能性がない場合は、`of()`を、`ofNullable()`を使うよ。
`of()`の使い方はこちら。
```java
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        final Optional<String> str = Optional.of("nullではありません。");
        System.out.print(str);
    }
}
```
```
// 処理結果
nullではありません。
```
`ofNullable()`の使い方はこちら。値を持っていた場合はその値を、値を持っていなかった場合は`orElse()`に記載した内容が返るように設定できるよ。

```Java
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        String val = null;
        final var sample = Optional.ofNullable(val).orElse("nullです。");
        System.out.print(sample);
```
```
// 処理結果
nullです。
```
他にも`orElseGet()`や`orElseThrow()`などの値を返すこともできるよ。今回は省略するよ。他によく使うメソッドを紹介するよ。

### filter()
値が存在し、それが指定されたものに一致する場合はその値を記述するOptionalを返し、そうでない場合は空のOptionalを返すよ。
```java
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        final Optional<String> val = Optional.of("ABC");
        final Optional<String> valFilter = val.filter(r -> r.length() > 5);
        System.out.print(valFilter);
    }
}
```
```
// 処理結果
Optional.empty
```

### ifPresent()
`ifPresent()`はインスタンスに、値が存在する場合はtrueを返し、ラムダ式を実行するよ。
```Java
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        final Optional<String> val = Optional.of("nullではありません。");
        val.ifPresent(r -> System.out.println(r));
```
```
// 処理結果
nullではありません。
```
### ifPresentOrElse()
`ifPresentOrElse()`はインスタンスに、値が存在する場合は第一引数で指定したラムダ式を、値が存在しない場合は第二引数で指定したラムダ式を実行するよ。
```Java
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        final Optional<String> val = Optional.empty();
        val.ifPresentOrElse(
            r -> System.out.println(r),
            () -> System.out.println("空です。"));
```
```
// 処理結果
空です。
```

### map()
`map()`は、処理結果を持ったOptionalのインスタンスを新たに生成して、その参照を戻すメソッドだよ。
```java
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        final Optional<String> val = Optional.of("abc");
        final Optional<String> mapVal = val.map(r -> r.toUpperCase());
        System.out.println(val);
        System.out.println(mapVal);
```
```
// 処理結果
Optional[abc]
Optional[ABC]
```
### flatMap()
通常の`map()`でOptional型に変換すると、`Optional<Optional<?>>`といった入れ子構造になってしまうけど、`flatMap()`を使うと要素の次元を下げることができるよ。
```Java
import java.util.Optional;

public class Main {
    public static void main(String[] args) {
        final Optional<String> val_1 = Optional.of("ABC");
        final Optional<String> val_2 = val_1.flatMap(r -> "ABC".equals(r)
            ? Optional.of(r + "DEF")
            : Optional.empty()
        );
        System.out.print(val_2);
```
```
// 処理結果
Optional[ABCDEF]
```

## まとめ
以上がOptionalについての解説だよ。nullかもしれない値が返ってくる場合は、Optional型を使って書くのがいいね。