我已经注意到Oracle JDK中的许多Java 8方法使用Objects.requireNonNull(),如果给定的对象(参数)为空,它会在内部抛出NullPointerException。
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
但是如果空对象被解引用,无论如何都会抛出NullPointerException。那么,为什么要做这个额外的空检查并抛出
NullPointerException吗?
一个明显的答案(或好处)是它使代码更具可读性,我同意这一点。我很想知道使用的其他原因
方法开头的Objects.requireNonNull()。
除了所有正确答案之外:
我们在反应流中使用它。通常产生的nullpointerexception根据它们在流中的出现情况被包装成其他异常。因此,我们以后可以很容易地决定如何处理错误。
举个例子:假设你有
<T> T parseAndValidate(String payload) throws ParsingException { ... };
<T> T save(T t) throws DBAccessException { ... };
其中parseAndValidate从ParsingException中的requireNonNull中wrapps NullPointerException。
现在你可以决定,例如什么时候重试或不重试:
...
.map(this::parseAndValidate)
.map(this::save)
.retry(Retry.<T>allBut(ParsingException.class))
如果不进行检查,将在save方法中发生NullPointerException,这将导致无休止的重试。甚至值得,想象一个长寿的订阅,补充道
.onErrorContinue(
throwable -> throwable.getClass().equals(ParsingException.class),
parsingExceptionConsumer()
)
现在retryextrestexception将终止您的订阅。
除了其他答案-对我来说,使用requireNonNull可以使代码更方便,(有时容易阅读)
例如,让我们检查下面的代码,
private int calculateStringLength(String input) {
return Objects.
requireNonNull(input, "input cannot be null").
length();
}
这段代码返回传递给它的字符串长度作为参数——但是如果输入为空,它将抛出一个NPE。
正如您所看到的,使用requireNonNull -没有理由再手动执行空检查了。
另一个有用的东西是“异常消息”是我自己手写的(在这种情况下输入不能为空)。
作为旁注,在object# requireNotNull之前,在java-9之前的一些jre类中实现的这个失败速度略有不同。假设如下情况:
Consumer<String> consumer = System.out::println;
在java-8中,编译为(仅相关部分)
getstatic Field java/lang/System.out
invokevirtual java/lang/Object.getClass
基本上是一个操作:yourReference。getClass -如果你的引用为空,它将失败。
在jdk-9中发生了变化,相同的代码编译为
getstatic Field java/lang/System.out
invokestatic java/util/Objects.requireNonNull
或者基本上是对象。requireNotNull(一份)