requireNonNull()
メソッドの最初のステートメントとして使用すると、例外の原因をすぐに特定できます。
スタックトレースは、呼び出し元が要件/契約を尊重しなかったため、メソッドのエントリと同時に例外がスローされたことを明確に示しています。
渡すnull
別のメソッドにオブジェクトはあり確かに一度の例外を引き起こすが、問題の原因は、例外が上の特定の呼び出しでスローされるように理解することは、より複雑かもしれnull
更に多くかもしれオブジェクト。
ここでは、一般的に高速で失敗優先する必要があり、より具体使っ理由を示しているコンクリートと実際の例であるObject.requireNonNull()
かどうかになるように設計パラメータにはヌルチェックを実行する方法はnull
。
に含まれる単語を表すDictionary
a LookupService
とa を構成するクラスを想定します。これらのフィールドはそうではないように設計されており、これらの1つが コンストラクターに渡され ます。 List
String
null
Dictionary
ここで、メソッドエントリ(ここではコンストラクタです)にチェックを付けDictionary
ない「悪い」実装を想定しますnull
。
public class Dictionary {
private final List<String> words;
private final LookupService lookupService;
public Dictionary(List<String> words) {
this.words = this.words;
this.lookupService = new LookupService(words);
}
public boolean isFirstElement(String userData) {
return lookupService.isFirstElement(userData);
}
}
public class LookupService {
List<String> words;
public LookupService(List<String> words) {
this.words = words;
}
public boolean isFirstElement(String userData) {
return words.get(0).contains(userData);
}
}
次に、パラメーターの参照を使用Dictionary
してコンストラクターを呼び出します。null
words
Dictionary dictionary = new Dictionary(null);
// exception thrown lately : only in the next statement
boolean isFirstElement = dictionary.isFirstElement("anyThing");
JVMは次のステートメントでNPEをスローします。
return words.get(0).contains(userData);
スレッド「メイン」の例外java.lang.NullPointerException
LookupService.isFirstElement(LookupService.java:5)で
Dictionary.isFirstElement(Dictionary.java:15)で
Dictionary.main(Dictionary.java:22)で
例外はLookupService
クラスでトリガーされますが、その発生元はかなり早いです(Dictionary
コンストラクタ)。これにより、全体的な問題分析があまり明白でなくなります。
ですかwords
null
?ですかwords.get(0) null
?両方とも ?なぜ一方、他方、あるいは両方がnull
そうなのでしょうか。それはコーディングエラーですか?Dictionary
(コンストラクタ?呼び出されたメソッド?)のですか?それはコーディングエラーLookupService
ですか?(コンストラクタ?呼び出されたメソッド?)?
最後に、エラーの原因を見つけるためにさらにコードを検査する必要があります。さらに複雑なクラスでは、デバッガを使用して、何が起こったのかをより簡単に理解できます。
しかし、なぜ単純なもの(nullチェックの欠如)が複雑な問題になるのでしょうか。
想像してみろ
それは、特定のコンポーネントで特定された初期のバグ/欠如を下位コンポーネントのリークで許可したためです。
LookupService
がローカルサービスではなく、リモートサービスまたはデバッグ情報の少ないサードパーティのライブラリであると想像してください。または、2層ではなく4層または5層のオブジェクト呼び出しnull
が検出される前に想像してみてください。問題はさらに分析が複雑になります。
したがって、支持する方法は次のとおりです。
public Dictionary(List<String> words) {
this.words = Objects.requireNonNull(words);
this.lookupService = new LookupService(words);
}
このようにして、頭痛の種はありません。これを受け取るとすぐに例外がスローされます。
// exception thrown early : in the constructor
Dictionary dictionary = new Dictionary(null);
// we never arrive here
boolean isFirstElement = dictionary.isFirstElement("anyThing");
スレッド「メイン」の例外java.lang.NullPointerException
java.util.Objects.requireNonNull(Objects.java:203)で
com.Dictionary。(Dictionary.java:15)で
com.Dictionary.main(Dictionary.java:24)で
ここではコンストラクターで問題を説明しましたが、メソッドの呼び出しで同じnull以外のチェック制約を設定できることに注意してください。