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;
}
}
}