Java8のOptionalの使い所
そもそもOptionalとは
Optional
Nullオブジェクトに近い感じでしょうか。
どういったところで使うのか
・Streamメソッドの返却値としてOptional型を返すのがいくつかあるので(findFirst,findAny,min,max,flatMap,etc...)
その返却値に対して処理を追加したいとき。
・メソッドの返却値がnullである可能性を明示的に示したいとき。
・煩わしいnullチェックの処理を除きたいとき。
・NullPointerExceptionのハンドリングに対して強いコードを書きたいとき。
Optionalの使用例
Optional#isPresent サンプルコード
public static void main(String[] args) { Optional<String> opt = Optional.ofNullable(doSomething()); if (opt.isPresent()) { System.out.println("It's not null !!"); } } static String doSomething() { return null; }
これだと普通にnullチェックをしているのと変わらないので、こういった使い方はあまりよくなさそうです。
そこで、下記のように修正。
Optional#ifPresent サンプルコード
public static void main(String[] args) { Optional<String> opt = Optional.ofNullable(doSomething()); opt.ifPresent(s -> System.out.println("It's not null !!")); } static String doSomething() { return null; }
劇的ではないにしろ、少しスッキリしました。
他にもいろいろと便利なメソッドが
nullの場合にデフォルト値を設定することができる Optional#orElse
サンプルコード
public static void main(String[] args) { // optionalの値がnullの場合 Optional<String> opt = Optional.ofNullable(doSomething()); String str = opt.orElse("Default"); System.out.println(str); // Default //optionalの値がnullでない場合 Optional<String> opt2 = Optional.ofNullable(doSomething2()); String str2 = opt2.orElse("Default"); System.out.println(str2); // Done something } static String doSomething() { return null; } static String doSomething2() { return "Done something"; }
nullの場合にデフォルト値を設定する"関数"を引数に設定することができる Optional#orElseGet
サンプルコード
public static void main(String[] args) { // optionalの値がnullの場合 Optional<String> opt = Optional.ofNullable(doSomething()); String str = opt.orElseGet(() -> "Default"); System.out.println(str); // Default //optionalの値がnullでない場合 Optional<String> opt2 = Optional.ofNullable(doSomething2()); String str2 = opt2.orElseGet(() -> "Default"); System.out.println(str2); // Done something } static String doSomething() { return null; } static String doSomething2() { return "Done something"; }
Optionalの値をfilterする
Optional#filterサンプルコード
public static void main(String[] args) { // optionalの値をfilter Optional<String> opt3 = Optional.ofNullable("abc"); // "a"で始まる文字列のみ抽出 opt3.filter(x -> x.startsWith("a")); String str3 = opt3.orElseGet(() -> "Default"); System.out.println(str3); // abc
Streamメソッドを使ってのOptional
サンプルコード
public static void main(String[] args) { // listの最初の文字列を表示 List<String> list = Arrays.asList("a", "b", "c"); Optional<String> opt = list.stream().findFirst(); opt.ifPresent(s -> System.out.println(s)); // a // listの最大の数値を取得 List<Integer> list2 = Arrays.asList(1, 2, 3); Optional<Integer> opt2 = list2.stream().max(Comparator.naturalOrder()); opt2.ifPresent(s -> System.out.println(s)); // 3 }
まとめ
上記メソッド以外にもいろいろとメソッドがあって、全部を全部使うということはないと思うけど、いろんなパターンを自分のローカルで試したりするとなかなか面白いです。
ひとまず、Optionalを使うときは#isPresentや#getを使わないのが良さそうなので、そこだけ気をつければ今後ヌルポやnullチェックには悩まされたりすることが少なくなるのかもしれない。
参考
http://www.ne.jp/asahi/hishidama/home/tech/java/optional.html
http://mike-neck.hatenadiary.com/entry/2014/10/05/211758
http://www.javazuki.com/articles/javase/optional-usage.html
http://d.hatena.ne.jp/nowokay/20130524
http://enterprisegeeks.hatenablog.com/entry/2014/07/28/094300