mike-neckのブログ

Java or Groovy or Swift or Golang

Java8のOptionalの使い方メモ

こんにちわ、みけです。

2014/10/10のScala勉強会に向けてScalaをやってたら、

Optional<T>の自分でもいいと感じる書き方がわかってきたつもりなので、

メモ書きしておきます。


Optional<T>を使うときの自分的なベストプラクティス。

  • #isPresentは使わない
  • 極力#map(Function<T, R>)#filter(Predicate<T>)#flatMap(Function<T, Optional<R>)を用いる
  • 最後に#orElse(T)#orElseGet(Supplier<T>)を用いる

#isPresentは使わない

これは使わないというよりは、むしろ、

使う機会がほとんどない感じがします。

最初、Optional<T>を使ってみたときは、

これまでのnullチェック脳の延長で

下のようにすぐifにぶっこんでいました。

int port;
Optional<String> envPort = Optional.ofNullable(System.getenv("PORT"));
if(envPort.isPresent()) {
    /*省略*/
} else {
    port = 8324;
}

しかし、このコードの書き方は、

単純にnullチェックがisPresentに変わっただけなので、

コードが読みやすくなったかというと答えはノーという感じです。

また、Optional<T>で受け取った値は、

その後に何らかの変換をかけてから使うことが多いので、

あまり意味無い感じがします。

極力(ry

では、今だとどういう感じに書いているかというと、

こんな感じです。

int port = Optional.ofNullable(System.getenv("PORT"))
        .filter(p -> Pattern.compile("^\\d+$").matcher(p).matches())
        .map(Integer::parseInt)
        .orElse(8324);

このような形であれば、

nullチェック、もとい、isPresentチェックをはさまずに

値の変換過程を追うことができます。

最後に(ry

#getを使わないのは、NoSuchElementExceptionが発生するからで、

それならorElseThrowでその処理に合わせた例外をはいたほうがいいですね。

というか、Optional<T>を使う時点で、

その値にはnullが含まれていることが想定されるので、

#getを使うことはほとんどないのではないかと思いました。


というか、OptionalIntとか用意するならmapToIntとか用意しておいたほうが(ry

以上