在Kotlin中大家会用{} ?: {}
来代替? {} : {}
表达式使用,?:
被称为Kotlin的Elvis表达式。
问题
读下面这段代码,大家看看它的打印值会是什么?
class Pack {
var text: String? = ""
fun foo() {
val result: String? = text?.run {
println("block 1")
null
} ?: run {
println("block 2")
"B"
}
println("result = '$result'")
}
}
输出结果:
block 1
block 2
result = 'B'
是不是和你意想中的结果不一样?
分析
我们来看看代码的执行过程:
-
STEP1 当
text
不为null
时,?.
判断通过,执行“block 1”所在的run
代码块 -
STEP2 当“block 1”所在的
run
代码块返回null
时,text?.run {}
被看做一个整体亦为```null`` -
STEP3 执行
null ?: run {}
的判断,?:
之前为null
,跟text
为null
是同一个概念,因此?:
判断通过,执行“block 2”所在的run
代码块
解决方案
这个问题的重点在于val result
的接受类型是String?
而不是String
。
当代码修改为如下时,这个问题就可以避免:
class Pack {
companion object val EMPTY_STRING: String = ""
var text: String? = ""
fun foo() {
val result: String = text?.run {
println("block 1")
EMPTY_STRING
} ?: run {
println("block 2")
"B"
}
println("result = '$result'")
}
}
总结
- 当表达式接收值为
val result: String
时,此代码块是一个if...else...
表达式 - 当表达式接收值为
val result: String?
时,此代码块是一个switch...case
表达式