Java8 の Optional とガード節

公開日: : 最終更新日:2015/01/12 Java ,

メソッドの冒頭で条件チェックを行い、条件を満たしていない場合はさっさと return してしまう「ガード節」を取り入れる癖が付いている。

Java8 から Optional が導入されたが、この Optional を引数で受け取るメソッドの場合、ガード節をどうやって書けばいいのかしっくり来ていない。

Optional に触れる機会を増やしてきたことで、何かヒントになりそうなコードが書けるようになってきたのでメモしておく。

icatch_4610898091

photo credit: Niccolò Caranti via photopin cc

目次

1. ガード節とは

新装版 リファクタリング―既存のコードを安全に改善する―(ボクが当時読んだのは旧版)を読んでガード節を知った。

優れた技術書をいくら読んでもそれを活かせないようでは意味がないので、「さらっと取り入れられそうなリファクタリングはどれか?」と考えたときに目にとまったのが「ガード節」だった。

ガード節については Strategic Choice さんから引用しておく。

if-then-else構文を使う場合、if/thenの分岐先とelseの分岐先には同等のウェイトを置いています。両方の分岐先が同じように実行され、重要だということを読者に伝えます。それに対し、ガード節は「これはまれなケースで、発生した場合には何かちょっとしたことを行って外に出る」ということを明確に表現することができます。

Replace Nested Conditional with Guard Clauses – Strategic Choice

2. Optional 型を受け取らないメソッドの場合

Java7 以前でのガード節。

null チェックをして、null なら return してしまう。早い段階で return することで、その後は null の可能性を排除してコードが読める。

Hoge hoge = getHoge(key);
if(Objects. isNull(hoge)) {
    return "not_found"; // 取得できなかったので "not_found" を返す
}

// hoge が null じゃなかった場合の処理
doSomething();
return "success"; // `doSomething()` をしたあとは "success" を返す

コードは変数の値や処理の流れなどいろいろ覚えながら読む。ガード節を取り入れることで、覚える数が減ったり可能性が排除できるので読みやすくなるので個人的にとても気に入っている。

2-1. 備考1

hoge が null であっては困るとか、そもそも null だとバグという場合は Objects.requireNonNull(hoge) を使って引数を確認する方法もある。

このメソッドを使った場合、null だと NullPointerException が発生するようになっている。1行で書けるから記述量が減るが、 NullPointerException なのでパッと見てすぐに不正な引数だったことが分かりにくいと思っている。

2-2. 備考2

ここでは例として null チェックを取り上げているが、当然 null 以外の条件チェックもガード節に含まれる。

3. Optional を受け取っただけのしっくり来ない書き方

Optional は使っているが、Java7 以前と同じ書き方。

getHoge() の戻り値が Optional になっただけで、ガード節の書き方自体は Java7 以前と同じというちょっとアレな書き方。

Optinal<Hoge> hoge = getHoge(key);
if(!hoge.isPresent()) {
    return "not_found"; // 取得できなかったので "not_found" を返す
}

// hoge が null じゃなかった場合の処理
doSomething();
return "success"; // `doSomething()` をしたあとは "success" を返す

全然それっぽくないし、こういうコードを書いてはいけないんだろうと思っている。

4. 今のところ Optional を使った場合はこうやって書くんだろうと思っている書き方

こんな感じにしか書けないんじゃないかと思っているから受け入れざるを得ない状態になっている。まだ馴染めない。

Optional<String> result = getHoge(key).map(h -> {
    // hoge が null じゃなかった場合の処理
    doSomething();
    return "success"; // `doSomething()` をしたあとは "success" を返す
});
return result.orElse("not_found"); // 取得できなかったので "not_found" を返す

まだ馴染めないのは、「最初にガツンと return で跳ね返すのがガード節だ!」っという固定概念がジャマしているからなのか、まだラムダ式に馴染んでいないからなのか。

4-1. 備考3

上記の例では “success” とか “not_found” といった値を返したかったので Optional#map() を使っている。戻り値を返す必要がない場合は Optional#ifPresent() を使う。

いずれにしても if 文を使って条件分岐するのではなく、ラムダ式を使って「条件を満たした場合の処理」を繋げる。

これまでは return していたから(エディタがハイライトしてくれることもあって)見た目に分かりやすかったが、これからはインデントがそれに代わることになるのかもしれない。

5. 更新履歴

  • 2014/10/17
    • 初版作成
  • 2015/01/11
    • 文言を修正

6. この記事の内容について

この記事は Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング を読みながら個人的にまとめたことをメモした内容になっています。

調べ物から記事作成までの全て作業はプライベートな時間に行ったものであり、所属組織のリソースは消費していません。また、記事のアイデアも所属組織に由来していません。

記事の内容が必ずしも正しかったり、最新ではないおそれがあります。参考にされる分には構いませんが、記事の内容を取り入れたことによって発生した損害などの責任は負いません。ご利用は自己判断でお願いいたします。

Javaプログラマーなら習得しておきたい Java SE 8 実践プログラミング

  • 著者Cay S. Horstmann
  • 価格¥ 3,024(2014/10/17 時点)
  • 出版日2014-09-22
  • 商品ランキング24027 位
  • 大型本264 ページ
  • ISBN-104844336673
  • 出版社インプレス

Googleアドセンス用(PC)

  • このエントリーをはてなブックマークに追加
  • follow us in feedly

関連記事

GradleLogoReg

Gradle で Java アプリのプロジェクトを作成して Eclipse にインポートするまでの手順

Mac に SDKMAN! を使って Gradle をインストールしたので、実際にプロジェクトを作成

記事を読む

no image

ファイルに関するユーティリティ

ファイルに関するスニペットをいくつか書いた。いつかコピペする日が来ると思うのでメモしておく。 作成

記事を読む

no image

Stream#map()とStream#collect()を使ってListを生成する

Java8 から導入された Stream API も少しずつ慣れてきて、「そういえばこういうパターン

記事を読む

icatch-thumbnail

レスポンスにサムネイル画像を返す API のサンプル

今回は直接 ImageMagick は関係ありませんが、また画像ネタです。この辺りのことを仕事で扱っ

記事を読む

GradleLogoReg

SDKMAN!(GVM) を使って Mac に Gradle をインストールする

長らく Java のアプリ開発には Maven を使ってきたが、時代に取り残されている感じがするので

記事を読む

no image

Google Guava の Function を使った文字列加工の FluentIterable サンプル

お客様の都合上 Java7 で開発している案件があるのだが、Java8 の Function とか

記事を読む

medium_182531101

ClassLoader を使って getResourceAsStream で取得したファイルを UTF-8 で読み込む

よく使う割には覚えられず毎回調べている気がするので備忘録としてメモしておきます。 文字コードを指定し

記事を読む

no image

Functions#compose() を使って Function を合成するサンプル(Java8 との比較付き)

Java8 と GoogleGuava の Function について コードの違いを書いた。 その

記事を読む

no image

Jetty でシンプルなプロジェクトを作成してみた

プロトタイプを作成するなら Tomcat よりも Jetty のほうがさらっと出来そうだなぁ、と今さ

記事を読む

no image

Java から VBScript を使って Excel を印刷する

背景 Java のデスクトップアプリを作成していたときの要件に「Excel で作成された帳票を印刷

記事を読む

Googleアドセンス用(PC)

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


× 8 = 五十 六

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Googleアドセンス用(PC)

icatch-jersey_multi_pathparams
Jerseyの@PathParamはスラッシュの間に複数指定できる

http://hoge-api/user/{id}.{format}

icatch-vagrant_box_customize
VagrantのBoxファイルをカスタマイズして独自のBoxファイルを作成する

配布されている Vagrant の Box ファイルを使って検証環境を

icatch-2015-006-1
バリデーションチェックにJava8のOptionalを使ってスマートに書く(自分比)

Web アプリのバリデーションチェックにアノテーションを使うことが増え

icatch-2015-005-1
ユニットテストの偏りを防ぐ命名規則の付け方

ユニットテスト名に以下の命名規則を付けるようにして二ヶ月ぐらい経った。

icatch-2015-004-1
Vagrantで起動したCentOS上のOctopressをホストOSから確認する設定

タイトルの通りだが、Vagrant を使って起動した CentOS に

→もっと見る

PAGE TOP ↑