Kotlin空安全:为何用?.而非if判空?还有哪些优势?
Kotlin空安全:安全调用操作符
?. vs 空判断if语句 在学习Kotlin空安全时,有理论提到:Kotlin有针对NPE的有效解决方案。
先看一段会触发NPE的代码(代码1):
class Foo { val c: String // Non-nullable init { bar() c = "" // Initialised for the first time here } fun bar() { println(c.length) // Oh dear } } fun main(args: Array<String>) { Foo() }
这段代码的问题在于init块中先调用了bar(),此时非空属性c尚未完成初始化,因此执行println(c.length)时会抛出空指针异常。
为避免这类空指针问题,Kotlin提供了?.安全调用操作符,示例代码(代码2)如下:
val c: String? = null fun bar() { print(c?.length) }
当然,我们也可以用传统的if语句做空判断:
fun bar() { if(c != null){ print(c.length) } }
问题解答
1. 既然可以使用if语句进行空判断,为何要采用?.的写法?
?.的优势远不止简洁,核心价值体现在这些场景:
- 链式调用更流畅:如果是多层嵌套的可空对象(比如
user?.address?.city?.name),用?.可以一行完成安全调用;换成if判断则需要多层嵌套,代码会变得冗余且难以阅读。 - 自动处理空值分支:
?.在遇到空值时直接返回null,无需手动编写else分支。比如需要获取可空长度时,val len = c?.length直接就能得到Int?类型的值,而if判断需要额外处理空值场景的返回逻辑。 - 与其他空安全特性无缝结合:可以和Elvis操作符
?:搭配快速设置默认值,比如val len = c?.length ?: 0,一行代码就能完成“空值时返回0”的逻辑,if判断要实现同样效果需要更多代码。 - 规避智能转换的局限性:在lambda、跨函数调用等复杂作用域中,Kotlin的智能转换可能无法识别if判断后的非空性,此时
?.能确保调用始终安全,而if判断可能会触发编译错误。
2. 仅仅是因为代码更简洁吗,还是存在其他未留意到的优势?
当然不只是简洁。除了上面提到的几点,?.的写法更贴合Kotlin的空安全设计理念,代码意图更清晰——一眼就能识别这是针对可空对象的安全操作,而if判断的空检查很容易和业务逻辑的条件判断混在一起,增加代码的理解成本。此外,?.在编译层面的处理更高效,编译器能针对安全调用做特定优化,而if判断的空检查则是通用的条件分支处理。
内容的提问来源于stack exchange,提问作者Ash Kecthum
相关产品推荐
相关产品推荐

