JavaのOptionalを使ってみたら手放せなくなった

こんにちは、アーキテクトのQZ西垣です。
平成最後の開発者ブログになります。
今回はJava8で導入されたOptionalについての話です。

Optionalって?

Optionalは前述のとおりJava8で導入された新しいクラスです。
当然興味を持ったので調べてみたところ、JavaDocで以下のように説明されています。

null以外の値が含まれている場合も含まれていない場合もあるコンテナ・オブジェクトです。

なんだかよくわからない。
Stream APIと対になる機能とのことですが、正直これだけでは何が便利なのかさっぱり分かりませんでした。
そんなわけで、Java8導入後もOptionalを使用しないコーディングを続けていたのです。

わからないけれど

それからしばらくはモヤモヤした日々を過ごしていました。
Optionalを使用することはないものの、ずっと考えて続けていたのです。
わざわざ追加されたクラスなのですから、きっと何か使い道があるに違いない。

Optionalと同時に導入されたStream APIについては多用していました。
その過程で関数型言語に関する知識も少しながら深めていくことになります。
また、同僚のゆうみさんとSlackで関数型言語的にどういう記述が望ましいかについても話しました。

ひらめいた

そんなある日、ふと突然トイレの個室でひらめいたのです。
まずは以下のコードをご覧ください。

このコードには以下の問題があります。

  • メソッド間に強い依存関係が存在している

問題を解決してみます。

  • メソッド間に依存関係はない

しかし別の問題が発生しています。

  • カッコが多重にカスケードされていて読みづらい(コードの読みやすさは大切です!)

さらに問題を解決します。

  • メソッド間に依存関係はない
  • カッコはシンプルなので読みやすい

しかしまた別の問題が発生してしまいました。

  • スコープのわりに実際に使用される期間が短い変数がいくつもある

ここでOptionalの出番です。

  • メソッド間に依存関係はない
  • カッコは2重までなので許容範囲内
  • 使用される期間が短い変数はラムダ式内に閉じ込められるためスコープは狭い

なんと、問題を全て解決できてしまいました。
しかも、このコードはさらに最適化可能なのです。

ラムダ式をメソッド参照に置き換え、Optional::getの使用をやめOptional::ifPresentを使用することにより、mainメソッドからすべての変数を除去できてしまいました。

いくつかの変数を元に新しい変数を作り出し、さらにそれを元に次の新しい変数を作り出す。
プログラムで散見するこの流れにおいて、Optionalは極めて強力な記法であることを、遅まきながら理解しました。

理解した以上は使わなければ勿体無い。
さまざまなケースでOptionalを使ってみることにより、さらに理解を深めました。
その結果、Optionalのことがよく分からなくても、使ってみると便利なケースも見えてきます。

カスケードしたMapOptionalを組み合わせる

一番手っ取り早くOptionalの効果が分かるのは、カスケードされたMapから値を取得する場合ではないでしょうか。
まずはOptionalを使わない場合のサンプルを見てください。

Mapからgetするごとにnullチェックを行わないとNullPointerExceptionが発生する恐れがあるため、非常に冗長なコードに見えます。

一方、Optionalを使う場合のサンプルです。

Optionalは、nullの場合処理がorElse系までジャンプするのでこのような記述ができます。
さらにこれをFunctionと組み合わせることにより、Mapに近い使い勝手でNullPointerExceptionの発生を回避することができます。

まずはFunctionを使わないサンプルです。

コメントのとおり、NullPointerExceptionが発生する可能性があります。

次にFunctionを使うサンプルです。

NullPointerExceptionの発生を気にする必要がなくなったのがお分かりいただけるでしょうか。

おわりに

Optionalは、工夫次第で可読性向上のためのさまざまなメリットを享受できる、非常に強力なクラスになります。
ストリームに比べると少し分かりにくいですが、ストリームに負けず劣らず便利な機能であることは間違いありません。
Java9からはifPresentOrElseが追加され、さらに便利になっています。
説明されてもなんだかよく分からないという方もいらっしゃるとは思います。
自分も当初はどう使えばいいのかまるで見当がつきませんでした。
しかし、使ってみればOptionalの便利さが身にしみて理解できるはずです。
まずは使ってみましょう!