Optionalクラスについて
詳しい説明はJavaDocを見てくださいという形だと何のためにこれ書いてるんだって話なので、Optionalクラスについて簡単に説明するとnullかどうか分からないデータを扱う時に便利になります。
実はJava8に開発環境を移してしばらく経ちますが、実は別に今までの書き方でいいやとスルーしてました。
しかし、使ってみて驚き使わなかったことに後悔しました。
そんなOptionalクラスについてさらっと書いていきたいと思います。
JavaDocの場所
Optionalの作り方
Optional.ofNullable("aaa")
Optional.of("aaa")
作り方はnewするのではなく、of
ofNullable
を使って値を作り出します。
2つの違いは名前が表していて、nullableのものはofNullable
を使いnonnullのものはof
を使います。
of
はObjects.requireNonNull
で値チェックしてるので、nullを渡すとNullPointerException
が発生します。
Optionalクラスから値を取得する
取得の仕方についてもnonnullである必要がある場合、nullableである場合で取得の仕方が違います。
まずはnonnullのケースから
get()
orElseThrow(Supplier<? extends X> exceptionSupplier)
get
はnullの場合、NullPointerException
が発生します。
orElseThrow
はnullだった場合のExceptionを引数でコントール出来ます。
Exceptionをコントールしたいかで使うメソッドを使い分けるだけです。
次にnullableのケースです。
orElse(T other)
orElseGet(Supplier<? extends T> other)
orElse
はOptionalの値がnullだった場合の値を引数で渡して使います(デフォルト値を渡すイメージ)。
引数はそのまま使われるので、ここにnullを入れても問題ありません。
orElseGet
はOptionalの値がnullだった場合、otherで渡したSupplierのgetを呼び出しその値が返却されます。
Optionalの値はnullableでも大丈夫ですが、Supplierの方はnonnullである必要があるので注意が必要です。
Stream的な使い方
Optionalクラスには値を変換するmap
flatmap
やフィルタリングするfilter
が実装されてるので、値があれば変換したいとかフィルターしたいというのを簡単に実装することが可能です。
値がないときは特に処理されないので、普通に便利です。
map
flatmap
の違いについては言葉で表すのが難しいので割愛します。
基本的にはmap
だけでどうにかなると思います。
データの存在チェック
isPresent()
ifPresent(Consumer<? super T> consumer)
isPresent
はデータが存在してればtrue、存在していければfalseが帰ってきます。
orElse
があるので、わざわざ値を取り出す時にチェックをする必要はありませんが、ないとそれはそれで困る感じです。
ifPresent
はデータが存在してれば実行するべきをラムダ式で渡すことで処理してくれる便利な子です。
void型なので単純に処理させるだけしか出来ませんが、取り出して処理をわざわざするのは面倒くさいですからね。
今回のために作ったサンプルソース
今回この記事を作るための動作確認用に作ったソースをのせておきます。
大したものではありませんが、参考になれば幸いです。
package javasample;
import java.util.Optional;
public class Main {
public static void main(String[] args) {
Optional<String> str = Optional.ofNullable("aaa");
Optional<String> str2 = Optional.ofNullable("");
Optional<String> str3 = Optional.ofNullable(null);
Optional<String> str4 = Optional.of("aaa");
Optional<String> str5 = Optional.of("");
// Optional<String> str6 = Optional.of(null);
Optional<Text> text = Optional.ofNullable(null);
Optional<Text> text2 = Optional.ofNullable(new Text());
System.out.println(str.get());
System.out.println(str2.get());
System.out.println(str3.orElse(null));
System.out.println("");
System.out.println(str4.get());
System.out.println(str5.get());
// System.out.println(str6.get());
System.out.println("");
System.out.println(text.orElse(null));
System.out.println(text.map(Text::getText).orElse("ccc"));
System.out.println(text.flatMap(text3 -> Optional.of(text3.text)).orElse(null));
System.out.println(text2.get());
System.out.println(text2.map(Text::getText2).get());
System.out.println(text2.flatMap(text3 -> Optional.of(text3.text)).orElse(null));
System.out.println("");
str.ifPresent(text3 -> System.out.println(text3 + text3));
str2.ifPresent(text3 -> System.out.println(text3 + text3));
str3.ifPresent(text3 -> System.out.println(text3 + text3));
}
public static class Text {
private String text = "aaa";
private String text2 = "bbb";
public String getText() {
return text;
}
public String getText2() {
return text2;
}
}
}