第8章 その他の Java 8 機能を理解する : 問題 14 : requireNonNull(T, Supplier<String>) メソッド
問題
java.util.Objects
のrequireNonNull(T, Supplier<String>)
メソッドは
- 第1引数が
null
かどうかをチェックし null
のときは第2引数のラムダ式を評価して- それをエラーメッセージとする
NullPointerException
をスローする
このメソッドによりもっと役立つエラーメッセージとなる方法を示せ。
疑問点
“よりもっと役立つエラーメッセージとなる” の意味が分からない。
本文には、次のサンプルコードがあった。
■ 本文のサンプルコード
this.directions = Objects.requireNonNull( directions, () -> "directions for " + this.goal + " must not be null" );
下のコードと比べれば、第2引数の文字列連結処理がnull
のときしか実行されないというメリットはあるんだが…
this.directions = Objects.requireNonNull( directions, "directions for " + this.goal + " must not be null" );
“よりもっと役立つエラーメッセージ” って何だろう?
解答
本文に載っているコードは、あるクラスのコンストラクタの一部だろうと思う。
goal とか directions というメンバー変数から推測するに、このクラスは「迷路を歩き回る経路」を表わしているのだろう。
話を簡単にするために、経路を進む方向は東西南北の4つしかないとする。
■ 経路を進む方向
public enum Direction { North, East, South, West }
■ requireNonNull
を使わない経路クラス
public class Path { private Point2D start; // 出発点 private Direction[] directions; // 経路を進む方向 public Path(Point2D start, Direction[] directions) { this.start = start; this.directions = directions; } // ゴールを求める public Point2D getGoal() { if (directions == null) { return start; } Point2D goal = new Point2D(start.getX(), start.getY()); for (Direction direction : directions) { switch (direction) { case North: goal = goal.add( 0.0, -1.0); break; case East: goal = goal.add( 1.0, 0.0); break; case South: goal = goal.add( 0.0, 1.0); break; case West: goal = goal.add(-1.0, 0.0); break; } } return goal; } }
このコンストラクタにrequireNonNull
メソッドを使ってnull
チェックを行うと
■ requireNonNull
を使ってnull
チェック
public Path(Point2D start, Direction[] directions) { this.start = Objects.requireNonNull(start, "~"); this.directions = Objects.requireNonNull( directions, () -> "directions for " + getGoal() + " must not be null" ); }
getGoal()
メソッドは、directions
がnull
でないときはコストが掛かる。
NullPointerException
がスローされないときも律儀にゴールを計算するのは無駄である。