Kotlin非空断言运算符(!!)异常行为:两段代码为何结果不同?
问题解答
首先明确两段代码的本质差异:
第一段代码中:
fun main() { var name: String? = null println(name!!.length) }
变量name被直接初始化为null,类型明确为String?。使用!!操作符时,编译器会允许这种写法(!!的作用就是强制解包可空类型,即便编译器能推断出值为null),因此代码能正常编译,但运行时因为实际值是null,触发NullPointerException。
第二段代码中:
fun main() { var name: String? = "Joe" name = null println(name!!.length) }
按逻辑来说,这段代码和第一段的运行行为应该完全一致——name最终是null,!!解包后会在运行时抛NPE。但你遇到的编译错误(Unresolved reference: length)是Kotlin 1.9.22版本的编译器类型推断bug:
当var类型的可空变量先被赋值为非空值、再重新赋值为null后,编译器在处理name!!时,错误地没有正确推断出解包后的类型为String,导致无法识别length属性。这种情况下代码无法通过编译,自然也就不会走到运行时抛NPE的环节。
这个bug在后续的Kotlin版本中已经被修复(比如1.9.23及以后版本),你可以尝试升级版本来解决这个问题。
内容的提问来源于stack exchange,提问作者0xBADABA55
相关产品推荐
相关产品推荐

