Kotlin 习语:空安全条件?

问题描述

在 Java 中,我会这样写:

if (foo != null && foo.bar()) { ...

然而,Kotlin 抱怨:

智能转换为 'Foo' 是不可能的,因为 'foo' 是一个可变属性,此时可能已经改变

认为是说我写的不是线程安全的。但是,在我使用它的上下文中,我知道它是这样的,因为它将始终在单个线程上调用

是的,foo 需要是可变的。我意识到将 foo 设为 val 可以解决这个问题,但在这里是不可能的。

Kotlin 中处理这种情况的正确习语是什么?

解决方法

诀窍是使用 Kotlin 出色的 null-safety operators 来避免进行冗余检查。

首先,我们使用安全调用运算符。

foo?.bar()

这是一个 Boolean?(即可以为 null 的布尔值),如果 foo 为 null,则为 null,否则为 bar() 的结果。现在,Boolean? 显然不是 if 语句中的有效条件,因此我们需要提供 false 的“默认”值。我们使用名字很有趣的 Elvis 运算符来做到这一点

if (foo?.bar() ?: false) { ... }

如果 foo 为 null,则 foo?.bar() 为 null,?: 返回右侧的值,即 false。如果 foo 为非空,则 foo?.bar() 是对 bar() 调用 foo 的结果,并且(假设该结果也是非空的),{{1} } 返回现有的非空布尔值。

,

在这种情况下,空安全调用返回一个布尔值?所以你可以检查它是否等于 true:

if (foo?.bar() == true) {

}

如果您需要在条件语句中使用非空的 foo,那么您可以使用常见的 ?.let 习语。

foo?.let { foo ->
    if (foo.bar()) {
    
    }
}

如果您知道它只能在同一个线程上访问,那么 !! 运算符在空检查后是安全的,但是 ?.let 更惯用,因此一旦您习惯阅读 Kotlin 就更容易理解.

,

如果条件不仅仅是函数调用,例如

utf8mb_bin

您可以使用 foo != null && foo.bar() > 0 let

run

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...