Kotlin空值检查与!!不短路评估?
在if语句评估中,Kotlin空安全检查是否未短路? 请参见下面的示例Kotlin空值检查与!!不短路评估?,kotlin,Kotlin,在if语句评估中,Kotlin空安全检查是否未短路? 请参见下面的示例 fun main(){ var myEmps : List<Emp>? = null println(myEmps) //null var address = if(myEmps?.get(0)!!.address?.line1!=null) myEmps?.get(0)!!.address!!.line1 else "no address" //Exception i
fun main(){
var myEmps : List<Emp>? = null
println(myEmps) //null
var address = if(myEmps?.get(0)!!.address?.line1!=null) myEmps?.get(0)!!.address!!.line1 else "no address" //Exception in thread "main" java.lang.NullPointerException
println(address)
}
data class Emp (var name: String?, var address: Address?) {}
data class Address(var line1: String?, var line2: String) {}
所以,请检查!!带有此短路警告不适用,始终确保正确检查整个链条?如果是这样的话,这在对象链验证的场景中有多有用?您应该将调用链看作是一系列计算结果的步骤。链上的每个调用都是在前面的评估值上调用的。任何
?。
调用都将计算为可为空的类型
首先是myEmps
,它是一个列表?
然后调用?。获取(0)
。由于null safe?。
调用,这将计算为一个Emp?
然后你调用代码>在Emp?
上<代码>
表示将其计算为不可为null的Emp
或抛出KotlinNullPointerException。它本质上与空安全调用相反
如果您想要空安全,您实际上需要的是继续使用空安全?。
一旦您有了可空的内容,就会调用整个链,因此您应该替换代码>与?
。像这样:
var address = if(myEmps?.get(0)?.address?.line1 != null) myEmps?.get(0)?.address!!.line1 else "no address"
第二次使用代码>可以保留,因为它发生在您的!=空值
检查,以便您知道Emp?
不会计算为空值
。但重复那长长的通话链是很笨拙的。通过使用Elvis运算符?:
可以消除此if语句,如下所示:
var address = myEmps?.get(0)?.address?.line1 ?: "no address"
你应该把一系列的调用看作是一系列的步骤,这些步骤对某些东西进行评估。链上的每个调用都是在前面的评估值上调用的。任何?。
调用都将计算为可为空的类型
首先是myEmps
,它是一个列表?
然后调用?。获取(0)
。由于null safe?。
调用,这将计算为一个Emp?
然后你调用代码>在Emp?
上<代码>
表示将其计算为不可为null的Emp
或抛出KotlinNullPointerException。它本质上与空安全调用相反
如果您想要空安全,您实际上需要的是继续使用空安全?。
一旦您有了可空的内容,就会调用整个链,因此您应该替换代码>与?
。像这样:
var address = if(myEmps?.get(0)?.address?.line1 != null) myEmps?.get(0)?.address!!.line1 else "no address"
第二次使用代码>可以保留,因为它发生在您的!=空值
检查,以便您知道Emp?
不会计算为空值
。但重复那长长的通话链是很笨拙的。通过使用Elvis运算符?:
可以消除此if语句,如下所示:
var address = myEmps?.get(0)?.address?.line1 ?: "no address"
你怎么看代码>是什么?因为它的目标是在再次遇到null
@a时抛出NullPointerException
,这里的要点是,如果您注意到,在此之前有一个null安全(?)评估。既然我的对象是空的,而且检查首先会失败,那么为什么下一部分要进行评估呢?谢谢。我想你不明白空安全属性访问是如何工作的。它只是将null
延迟到链的下游。如果空安全链的任何部分为null
,则整个过程将为null
,并添加一个代码>之后,它将抛出一个NullPointerException
,因为它是null
。为什么您认为get()
不应该得到计算obj?.call()
在两种情况下都返回null,如果previorobj
为null,当call
返回null时,基本上是null传播到下一个语句。可能您的意思是:myEmps?.get(0)?。让{if(it.address.line1!=null)…}
如果myEmps
中的任何一个null
或get
返回null
,您会忽略这些内容。您认为怎么样代码>是什么?因为它的目标是在再次遇到null
@a时抛出NullPointerException
,这里的要点是,如果您注意到,在此之前有一个null安全(?)评估。既然我的对象是空的,而且检查首先会失败,那么为什么下一部分要进行评估呢?谢谢。我想你不明白空安全属性访问是如何工作的。它只是将null
延迟到链的下游。如果空安全链的任何部分为null
,则整个过程将为null
,并添加一个代码>之后,它将抛出一个NullPointerException
,因为它是null
。为什么您认为get()
不应该得到计算obj?.call()
在两种情况下都返回null,如果previorobj
为null,当call
返回null时,基本上是null传播到下一个语句。可能您的意思是:myEmps?.get(0)?。让{if(it.address.line1!=null)…}
如果myEmps
中的任何一个null
或get
返回null
,则忽略某些内容。这就澄清了问题,非常感谢!这就澄清了,非常感谢!