引数の値が null だったときに、投げる例外はどちらが正しいのか?
まとめ
結論 -> どちらでも問題ない
JavaDocに記載されているとおり、どちらの状況も当てはまるから
IllegalArgumentException
不正な引数、または不適切な引数をメソッドに渡したことを示すためにスローされます。
NullPointerException
オブジェクトが必要な場合に、アプリケーションがnullを使おうとするとスローされます。
よく見かけるコードたちの例
public void setterMethod(Object par) {
if(par == null) {
throw new NullPointerException("par is null");
}
// do something...
}
public void setterMethod(Object par) {
if(par == null) {
throw new IllegalArgmentException("par is null");
}
// do something...
}
Java標準APIのソースコードは?
Objects#requireNonNull メソッドを通して NPE を投げている。
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
JavaDocを読んでみる
どちらも適切ということが分かった。
こりゃNPE派とIAE派がいるわけだ。
IllegalArgumentException
不正な引数、または不適切な引数をメソッドに渡したことを示すためにスローされます。
NullPointerException
オブジェクトが必要な場合に、アプリケーションがnullを使おうとするとスローされます。たとえば、次のような場合があります。
- nullオブジェクトのインスタンス・メソッドの呼出し。
- nullオブジェクトのフィールドに対するアクセスまたは変更。
- nullの長さを配列であるかのように取得。
- nullのスロットを配列であるかのようにアクセスまたは修正。
- nullをThrowable値であるかのようにスロー。
nullオブジェクトの不正な使用を示す場合は、このクラスのインスタンスをアプリケーション側でスローするようにしてください。まるで抑制が無効になっているか、スタック・トレースへの書込みができないか、あるいはその両方であるかのように、仮想マシンによってNullPointerExceptionオブジェクトが構築される可能性があります。
解決策
とあるライブラリでは?
apache commons-lang のライブラリでは IAEを継承したクラス NullArgumentException というクラスがある。これを用いてスローすると良いかもしれない。
NullArgumentException
引数にnullを渡した場合に、スローされます。
オマケ:もしかして、これでいいのでは?
ライブラリを使用することができない場合だと、こうなる。
賢すぎる開発者おったわ。「IAEでNPEをラップすれば良いじゃん」だそうです。
public void setterMethod(Object par) {
if(par == null) {
throw new IllegalArgmentException(new NullPointerException("par is null"));
}
// do something...
}