猫王运算符与非null断言:这些语句之间有区别吗?

时间:2018-07-18 01:47:52

标签: nullpointerexception kotlin type-safety kotlin-null-safety

试图了解Kotlin中的零安全性:以下两个语句似乎都可以正常工作,并且在我的程序中可以互换:

var y1: Double = 0.0
    get() = when(hasParent) {
        true -> parent!!.y1
        else -> field
    }

var y1: Double = 0.0
    get() = parent?.y1!!

({hasParent只是获取parent是否为空的吸气剂)

这两个在语义上是相同的还是实际上是不同的表示不同事物的表达?而且,如果它们在语义上意味着相同的意思,那么出于任何原因,有史以来优先使用第一个吗?

2 个答案:

答案 0 :(得分:2)

在这种情况下,您不需要hasParent。适用的格式是:\

var y1: Double = 0.0
    get() = parent?.y1 ?: field

第二个吸气剂的问题在于,无论如何它都会尝试返回parent.y1,如果不存在,它将抛出一个NullPointerException

如果使用IDEA,则会收到针对此类问题的警告,因此很容易解决,但您需要了解来自Java代码的所谓平台类型:

val queue: Queue<String> = LinkedList()
queue.peek().toInt()

此处,尽管可以从.toInt()中获取空值,但编译器不会抱怨Queue。我已经写过这个here

答案 1 :(得分:1)

请注意,jingx和Adam Arold的答案对于当前情况是有好处的,但是如果y1的类型为可空,则它并不等同于您的第一个代码段:如果parent不为空,但是parent.y1是,那么您的代码给出了null,而parent?.y1 ?: field给出了field

如果您需要第一种行为,我会说实际的首选形式是

if (parent != null) parent.y1 else field // if parent is val without a custom getter
parent.let { if (it != null) it.y1 else field } // otherwise

使用hasParent对您实际检查是否为null的编译器隐藏并且不需要!!