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

Elvis Operator vs Non-Null Assertion: Diff Between These Statements?

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

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

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

(hasParent 只是一个 getter 来查看 parent 是否为 null)

这两个在语义上是相同的还是它们实际上是指不同事物的不同表达方式?如果它们在语义上表示相同的意思,那么第一个是否出于任何原因比第二个更受欢迎?

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

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

你的第二个 getter 的问题是它会尝试 return 无论如何 parent.y1 如果它不存在它会抛出 NullPointerException .

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

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

这里编译器不会为 .toInt() 报错,尽管有可能从 Queue 中得到一个 null。我已经写过这个 here.

请注意,jingx 和 Adam Arold 的回答适合当前情况,但如果 y1 的类型可为空,则它不等同于您的第一个片段:如果 parent 不是null,但是 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 并且不需要 !!