如何解决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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。