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