迁移至Kotlin 2.0.0遇空安全编译错误与警告冲突问题
Kotlin 2.0.0迁移后空安全编译错误的原因与解决
你遇到的问题是Kotlin 2.0.0对智能转换规则进行了严格收紧,导致之前依赖跨条件分支的智能转换代码失效。
问题根源
在Kotlin 1.9.+中,编译器允许在执行myFrameRate!!后,后续语句自动将myFrameRate智能转换为非空类型——即使!!是在myConfig?.myFrameRate = ...这样的条件执行语句中(只有myConfig非空时才会执行)。但Kotlin 2.0.0不再认可这种跨条件分支的智能转换:因为myConfig?.myFrameRate = ...是条件执行的,如果myConfig为null,myFrameRate!!根本不会运行,myFrameRate依然可能为null。编译器现在会更严格地跟踪变量的非空状态,只有当非空断言在必然执行的代码路径中时,才会触发智能转换。
这就导致了矛盾:直接调用myFrameRate.toInt()会因为 receiver 可能为null报错,添加!!又会因为编译器在局部分析中认为变量已被断言过而提示“不必要的非空断言”。
解决方案
方案1:提前处理null并转换为Int(推荐)
将myFrameRate的转换逻辑提取到单独的语句中,一次处理null情况,避免重复操作:
val myConfig: Configuration? = null val myFrameRate: String? = getPreferences(Context.MODE_PRIVATE).getString("my_FrameRate", "0") // 提前处理null,默认转为0(或根据业务需求调整) val frameRate = myFrameRate?.toInt() ?: 0 // 若确定myFrameRate永远不为null(因为传入了默认值"0"),也可直接用!! // val frameRate = myFrameRate!!.toInt() myConfig?.myFrameRate = frameRate // 重复赋值的话直接复用frameRate即可 myConfig?.myFrameRate = frameRate
方案2:修正myFrameRate的类型为非空String
由于getString方法传入了非空默认值"0",实际返回值永远不会为null,因此可以直接将变量定义为非空类型,从根源避免空安全问题:
val myConfig: Configuration? = null // 定义为非空String,用Elvis运算符兜底(理论上不需要,但符合规范) val myFrameRate: String = getPreferences(Context.MODE_PRIVATE).getString("my_FrameRate", "0") ?: "0" val frameRate = myFrameRate.toInt() myConfig?.myFrameRate = frameRate
方案3:在赋值语句中直接处理null(不推荐,重复代码)
如果需要保留原有语句结构,可在每个赋值中用安全调用+Elvis运算符处理null:
myConfig?.myFrameRate = myFrameRate?.toInt() ?: 0
内容的提问来源于stack exchange,提问作者user23185393
相关产品推荐
相关产品推荐

