Optional#orElseについて勘違いしていた #java

JavaでOptionalの値取り出しにorElseを利用すると思うんだけど、その動きについて勘違いしていた。

Optional<Long> getId();

こんな感じのメソッドがある時、orElseでの値取り出しは下記の用になると思う。

Long id = getId().orElse(createId());

勘違いしてた所

前述の例の場合、createIdはOptionalがnull(empty)の場合にのみ呼ばれると思っていた。
ところが、orElseの処理自体は常に呼ばれるようだ。
イメージでいうと下記のような。

Long id = getId();
if (id == null) {
  // nullのときだけ呼ばれると思ってたけど、orElseはそうじゃない!!
  id = createId();
}

常に呼び出したくない場合はどうするか

例えばcreateIdの処理コストが高かったりする場合は、都度実行することは避けたい。
その場合はorElseGetを使うことで、Optionalがnull(empty)の場合にのみ呼ばれるようになる。

// orElseGetを使う
// OptionalがnullのときだけcreateIdが呼ばれる
Long id = getId().orElseGet(() -> createId());

気づいたきっかけ

メソッド呼び出し確認のUnitTestを書いているときに気づいた。
Test書くのって大事だなぁと改めて思うなどした。

参考

Optionalの取り扱いかた - 日々常々

Java 8 "Optional" ~ これからのnullとの付き合い方 ~ - Qiita