Objects#requireNonNull による null チェックのススメ
コンストラクタ・メソッドを書く際、引数が null になっていないかのチェックを書くのがめんどくさくて省略してしまうことはないだろうか? ...少なくとも私はめんどくさくて多くの場合省略してしまっていた。
しかし、Java 7 以降に入った Objects クラスなるものを使うと楽に書けるということを知ったので共有までに。
Usage
公式の説明を見ればわかる通り大変シンプル。
Objects.requireNonNull メソッドは引数が null なら NullPointerException を投げ、そうでないなら引数をそのまま返す。
class Hoge { private final String huga; public Hoge(String huga){ this.huga = Objects.requireNonNull(huga); } }
これは Objects を使わない以下のコードと等価である:
class Hoge { private final String huga; public Hoge(String huga){ if(huga == null) throw new NullPointerException(); this.huga = huga; } }
実際に Eclipse 上などで入力してみると、"Objects", ".", "requireNonNull" の 3 トークンだけで済む前者の方が、後者の if 文パターンよりも大分少ない手間で入力できる。
また、null チェックのためだけのコードが縦に長くならない点は可読性に良い (1 メソッドが長くなればなるほど読みづらい)。
加えて、requireNonNull はメソッドなので、文中のどこにでも挟めるのも地味に良い点である
public void doSomething(String huga){ this.hogehoge(Objects.requireNonNull(piyo)); // メソッド呼び出し前に null チェックされる }
ところで、null チェックって必要?
基本的に、エラーの原因とエラーの発生側の距離(コード上の場所や、実行タイミング)は近ければ近いほどよい。
距離が近くない場合、エラーが出てからその原因を特定するまでに時間を要してしまう。
Null チェックについてで言えば、フィールドに値を持つ場合、「フィールドに null を入れてしまった側」と、「そのフィールドの値を実際に使って NPE になってしまった側」のコード上の場所も実行タイミングも離れる。
それゆえに、NPE が発生してから、コードを辿ったり、あるいはもう一回プログラムを再実行してデバッガで追いかけなおすという手間*1が発生し開発効率が下がる。
よって、null チェックをしておくことは後々に自分や他人のためになる。
Objects#requireNonNull によって少ない負担で null チェックが出来るようになったことで、上記の null チェックのメリットがより得やすくなった(手間に対してメリットがペイするようになった)ので、これを機に null チェックする習慣をつけることを検討してはいかがだろうか。
*1:大概コードを追いにくいようなシロモノに限って作りもレガシーなので、プログラムの再実行のためにファイルやら何やらを整えなおすのに手間がかかり、実行してからエラーになるまで時間がかかり、例外トレースも汚くて...ということが多くつらい