JavaのOptional
(java.util.Optional
)がどういうものであるかについて自分なり理解したので、それについてメモしておきます。
自分なりの理解ということで、細かい部分で正しくないところもあるかもしれません。
Optionalの役割
Optional
は、値があるかもしれないし無い(null)かもしれない ことを表現するための型- nullに対してより安全な操作を提供する
Optionalをどういう方針で操作すればよいのか
- 値が存在するならばXXXという処理をする、値が存在しないならばYYYという処理をする という風に、値の存在有無によって実施する内容を明確にした指示をする
- 値が存在する場合の処理と値が存在しない場合の処理を同時に指示する必要がある(別々に指示しない)
- 値の存在有無が分からない状態での操作(値取得etc)は基本的にやるべきではない
どういう操作ができるか
例えば以下のような操作が提供される
Optional#ifPresent
- 値が存在すれば指定された処理を実行する(値が存在しなければ何もしない)
Optional#filter
- 値が存在していてかつ引数の条件に一致する場合は元のOptionalを返す、値が存在しない場合や値は存在するが条件に一致しない場合は空のOptionalを返す
Optional#orElse
- 値が存在すればその値を返し、存在しなければ引数で指定した値を返す
Optional#orElseGet
- 値が存在すればその値を返し、存在しなければ引数で指定した値の取得処理を呼び出しそれにより得られた結果を返す
Optional#orElseThrow
- 値が存在すればその値を返し、存在しなければ引数で指定した例外をスローする
使ってはいけないメソッド
以下のメソッドを使うとOptional
に課せられたはずの役割を果たすことができないので、基本的に使うべきではない
Optional#get
- 値の存在有無にかかわらず値を取得しようとする
Optional#isPresent
- 値の存在有無をチェックするだけで、値が存在すれば何をするのか、値が存在しなければ何をするのかという指示に至っていない
サンプル利用シーン
あるデータストアからRepositoryクラスを利用してデータを取得するが、Repositoryクラスはデータがあればそのデータを返すが、存在しない場合はnullを返す。
このような場面でのOptional
の一利用方法を以下に記載します。
以下のようなUser
クラスが仮に存在したとします
public class User { private final String id; private final boolean isEnabled; User(String id, boolean isEnabled) { this.id = id; this.isEnabled = isEnabled; } public String id() { return id; } public boolean isEnabled() { return isEnabled; } }
上記のUser
が複数格納されたデータストアを操作するためのUserRepository
というクラスが存在していて以下の仕様であるとします。
UserRepository#findById
は 引数のidに対応するUser
を返すUserRepository#findById
は、紐づくUser
がない場合は null を返す
という場合に、UserRepository#findById
の戻り値をOptional
を使って以下のように処理するコードが書けます
import java.util.Optional; UserRepository userRepository = ...; User user = Optional.ofNullable(userRepository.findById(id)) .filter(u -> u.isEnabled()) .orElseThrow(() -> new UserNotFoundException("user is not found or disable.")); System.out.println("user: " + user);
動作としてはUserRepository#findById
の戻り値に応じて以下のようになります
- Userのインスタンスがreturnされた、かつ、有効なUserであった
- ⇒ Userの内容がコンソールに出力される
- Userのインスタンスがreturnされた、かつ、無効なUserであった
- ⇒ UserNotFoundExceptionがスローされる
- nullがreturnされた
- ⇒ UserNotFoundExceptionがスローされる
というわけで、java.util.Optional
に関する自分なりの簡単な整理でした。