Kotlin安全调用?.执行逻辑疑问:为何test?.getname().isNullOrEmpty()返回Boolean
Kotlin安全调用与isNullOrEmpty()的疑问解答
问题背景
根据Kotlin官方文档中关于安全调用的说明:若调用链中任意属性为null,整个链返回null。原本的理解是,对于A?.B?.C,如果A为null,执行A?.时就会返回null并终止后续B?.C的执行。
但当?.与isNullOrEmpty()结合时,出现了和预期不符的情况:
- 当
test为null时,预期if(test?.getname().isNullOrEmpty())会抛出需要Boolean类型的异常 - 另外,
isNullOrEmpty()不能直接调用在null上,它需要Array<*>?这类对象 - 但实际代码会打印“isNullOrEmpty() is executed”
同时,如下代码无法编译(提示Unresolved reference),因为isNullOrEmpty()不能直接在null上调用:
if(test?.isNullOrEmpty()) { println("isNullOrEmpty() can be ran on null") } else { //TODO }
问题解答
1. Kotlin安全调用?.的执行逻辑
安全调用?.的核心规则很明确:如果调用者不为null,就执行后续的属性或方法调用;如果调用者是null,整个?.表达式直接返回null,并且不会执行后续紧跟的属性/方法调用。
这里容易混淆的是优先级:?.的优先级高于普通的.调用。比如test?.getname().isNullOrEmpty()会被Kotlin解析为(test?.getname()).isNullOrEmpty(),而不是把它当成连续的安全调用链。
2. 为何test?.getname().isNullOrEmpty()能返回Boolean类型?
问题的核心在于isNullOrEmpty()的实际接收者和Kotlin的扩展函数设计:
- 当
test为null时,test?.getname()的结果是null,这个null的类型是String?(假设getname()返回String) - Kotlin为
CharSequence?(String实现了该接口)提供了可空类型的扩展函数isNullOrEmpty(),它的逻辑是:接收者为null时直接返回true;非null时调用非空的isEmpty()方法。 - 你尝试的
test?.isNullOrEmpty()编译失败,是因为test本身的类型并不是Array<*>?、CharSequence?这类拥有isNullOrEmpty()扩展函数的可空类型,所以编译器找不到对应的方法,报Unresolved reference。
内容的提问来源于stack exchange,提问作者Chloe L
相关产品推荐
相关产品推荐

