こんにちわ、みけです。
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
以上