使用requireNonNull()
如在方法首先语句允许以确定现在/快异常的原因。
stacktrace清楚地表明,由于调用者不遵守需求/合同,因此在方法进入后立即引发了异常。
将null
对象传递给另一种方法确实确实可能一次引发一个异常,但是问题的原因可能更难以理解,因为该异常将在null
对象上的特定调用中引发,而该调用可能会更远。
这是一个具体的真实的例子,说明了为什么我们通常不得不快速失败,更特别的是使用Object.requireNonNull()
或任何方式对设计为not的参数进行no null检查null
。
假设一个Dictionary
类由a LookupService
和a 组成List
,String
表示包含在其中的单词。这些字段设计为not,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
不是本地服务,而是远程服务或带有很少调试信息的第三方库,或者想象在null
被检测到之前,您没有2层而是4或5层对象调用?问题将变得更加复杂。
因此,青睐的方法是:
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检查约束。