requireNotNull vs确定运算符!在科特林

ash*_*shu 7 kotlin codacy

我们有一个基于Kotlin的应用程序,最近我们添加了第三方代码质量工具(Codacy中的Detekt)。但是,我们开始遇到UnsafeCallOnNullableType错误。我们发现可行的方法是在所有可能为null的参数上添加requireNotNull检查。当前,我们正在使用肯定运算符(!!)

我们是否有任何特定的理由或约定选择一个而不是另一个。据我所知,两者都将抛出Exception并阻塞执行流程,除了一个将抛出IllegalArgumentException,而另一个将抛出NullPointerException。

Zoe*_*Zoe 7

requireNotNull假设您指的是Objects#requireNonNull, 是一个与 等效的 Java 方法!!,但有不同的例外。

你没有添加任何代码,所以帮助你调试有点困难。您提到了第三方代码质量工具,但没有提到是哪些。我偶然发现了这个 GH 问题,它与您遇到的错误相匹配。这也是我能找到的唯一可以在任何时候使用该确切错误的东西。我可能错过了一些,但它涵盖了 Google 的热门点击,所以我将不再讨论它。

如果您使用 Detekt,这是一个已报告的错误。!!IntelliJ 甚至建议使用。

但是,您可以采用另一种方式。

是的,使用Objects#requireNonNull是一种选择。不过还有第二个,那就是使用空安全运算符,如 m0skit0 提到的。

这样做的原因是,如果调用的任何内容为 null,则最终结果也为 null。即这个:

instance.nonNullType.nullable?.nullableChild?.someOtherNullableChild
Run Code Online (Sandbox Code Playgroud)

如果任何一个可为空的为空,则最终结果为空,并且不会调用其他任何一个。

现在,考虑到这可能是 Detect 中的一个错误,这似乎是目前最简单的解决方法:

whatever.calls.you?.make?.to?.the?.database ?: throw NullPointerException("Something is null");
Run Code Online (Sandbox Code Playgroud)

它还使变量保持非空,这意味着以后不需要空安全调用。elvis 运算符检查是否有任何内容为 null,然后引发异常。或者,您可以只使用Objects#requireNotNull

Objects.requireNonNull(whatever.calls.you.make.to.the.database)
Run Code Online (Sandbox Code Playgroud)

如果您确实需要验证每个步骤,则只需在各处保留空检查即可

长话短说:

!!它们requireNotNull的工作方式实际上是相同的,除了requireNotNull方法调用并!!编译为 if 语句:

if(whatever == null) {
    Intrinsics.throwNpe();
}
Run Code Online (Sandbox Code Playgroud)

!!触发的原因UnsafeCallOnNullableType是 Detekt 中的(可能)错误。不过,这两个选项都是同一事物的语法糖:如果变量为 null,则抛出 NPE。