猫王运算符与非空断言:这些语句之间的区别?

Posted

技术标签:

【中文标题】猫王运算符与非空断言:这些语句之间的区别?【英文标题】:Elvis Operator vs Non-Null Assertion: Diff Between These Statements? 【发布时间】:2018-12-25 19:21:29 【问题描述】:

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

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

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

hasParent 只是一个查看parent 是否为空的getter)

这两个在语义上是否相同,或者它们实际上是不同的表达方式,意味着不同的事物?如果它们在语义上的意思相同,那么出于某种原因,第一个是否优于第二个?

【问题讨论】:

第二种形式与第一种不同,不正确。如果parent 为空,您将得到NullPointerExceptionparent?.y1 ?: field 相当于第一种形式。 您能否将其移至答案以便我接受? 【参考方案1】:

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

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

您的第二个 getter 的问题是,无论如何它都会尝试返回 parent.y1,如果它不存在,它将抛出 NullPointerException

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

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

这里编译器不会为.toInt() 抱怨,尽管可以从Queue 获得空值。我已经写过这个here。

【讨论】:

【参考方案2】:

请注意,jingx 和 Adam Arold 的回答对当前情况很好,但如果 y1 的类型可以为空,则它不等于您的第一个 sn-p:如果 parent 不为空,而是 @ 987654323@ 是,那么你的代码给出nullparent?.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 对编译器隐藏了您实际检查是否为空并且不需要!!

【讨论】:

以上是关于猫王运算符与非空断言:这些语句之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

18 19 20 py if语句 比较运算符 断言assertions

RTL基本知识:阻塞赋值与非阻塞赋值

javascript 中是不是有空合并 (Elvis) 运算符或安全导航运算符?

Kotlin空安全 ③ ( 手动空安全管理 | 非空断言操作符 !! | 使用 if 语句判空 )

== , = 和 eq 之间的区别

python基础语法常用内置函数关键字方法和之间的区别(小结)