查看以下在Kotlin REPL中运行的代码:
>>> null.takeIf({1==2})
res4: kotlin.Nothing? = null
为什么这不会导致NullPointerException?
答案 0 :(得分:7)
您的代码不会导致NullPointerException,因为takeIf
是扩展函数。
扩展函数被转换为方法接收器,第一个参数是您在其上调用函数的对象。
因此,您可能想知道为什么下面的函数没有抛出NullPointerException而不是null.takeIf { false }
(简化您的示例):
fun <T> takeIf(me: T, predicate: (T) -> Boolean): T? {
...
}
好吧,为此,我们需要研究takeIf()
的实现(删除注释和协定):
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
return if (predicate(this)) this else null
}
因此,如果您的谓词为假(例如在您的示例中,1==2
),它将短路并返回null。
如果是true
,该怎么办?我们最终会得到一个NullPointer吗?
不是:
val nothing: Nothing? = null.takeIf {
true
}
答案 1 :(得分:0)
科特林针对类型的设计方法旨在有目的地消除NPE。如文档所示,可能触发条件的条件仅限于
第三个选项适用于NPE爱好者:非空声明运算符 (!!)将任何值转换为非null类型,并在出现以下情况时引发异常 该值为空。我们可以写b !!,这将返回非null b的值(例如,在我们的示例中为String),或者如果b为 空:
val l = b!!.length
因此,如果您需要NPE,可以拥有它,但是 必须明确要求它,并且它不会突然出现。
因此您的代码行为符合预期。请参阅链接以获取更多信息