为什么应该使用Objects.requireNonNull()?

441

我注意到Oracle JDK中许多Java 8方法都使用Objects.requireNonNull(),如果给定的对象(参数)为null,则会内部抛出NullPointerException

public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}

但是,如果引用了一个空对象,无论如何都会抛出NullPointerException。那么,为什么还要进行额外的空检查并抛出NullPointerException呢?

一个明显的答案(或好处)是它使代码更易读,我同意。我很想知道在方法开头使用Objects.requireNonNull()的其他原因。


44
https://en.wikipedia.org/wiki/Fail-fast - luk2302
4
这种参数检查方法可以让你在编写单元测试时作弊。Spring也有类似的工具(请参见https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/util/Assert.html)。如果你有一个“if”语句,并且想要高覆盖率的单元测试,你必须涵盖两个分支:当条件满足时和条件不满足时。如果你使用`Objects.requireNonNull`,你的代码没有分支,所以单元测试的一次通过就可以获得100%的覆盖率 :-) - xorcus
@javing,你打算如何确保没有人会传递空值而不出现错误呢? - SamB
我在这里是因为IntelliJ建议在任何地方都使用requireNonNull。如果下面的示例有意义,我必须承认IntelliJ建议的修复并不总是有效的。 - Christian Vincenzo Traina
显示剩余2条评论
12个回答

0
在实现Nullability检查的编译器扩展(例如:uber/NullAway)的情况下,应该谨慎使用Objects.requireNonNull,仅在您知道可为空字段在代码的某个特定点不为null时使用。
因此,有两种主要用途:
  • 验证

    • 已由其他响应覆盖
    • 运行时检查带有开销和潜在NPE
  • Nullability标记(从@Nullable更改为@Nonnull)

    • 最小化运行时检查,以支持编译时检查
    • 仅在注释正确时起作用(由编译器强制执行)
Nullability标记的示例用法:
@Nullable
Foo getFoo(boolean getNull) { return getNull ? null : new Foo(); }

// Changes contract from Nullable to Nonnull without compiler error
@Nonnull Foo myFoo = Objects.requireNonNull(getFoo(false));

0

除了所有正确的答案:

我们在响应式流中使用它。通常,由于其在流中的发生情况而将产生的NullpointerException包装成其他异常。因此,我们可以稍后轻松地决定如何处理错误。

举个例子:想象一下你有

<T> T parseAndValidate(String payload) throws ParsingException { ... };
<T> T save(T t) throws DBAccessException { ... };

parseAndValidate 包装了 requireNonNull 中的 NullPointerException,并抛出一个 ParsingException

现在你可以决定,例如何时进行重试或不重试:

...
.map(this::parseAndValidate)
.map(this::save)
.retry(Retry.<T>allBut(ParsingException.class))

没有这个检查,save 方法会抛出NullPointerException异常,这将导致无限重试。更糟糕的是,想象一下一个长时间存活的订阅,不断地添加。

.onErrorContinue(
    throwable -> throwable.getClass().equals(ParsingException.class),
    parsingExceptionConsumer()
)

现在,RetryExhaustException 将终止您的订阅。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接