在 Kotlin 中,两个 !!
(也称为 "not-null assertion operator")用于将一个可空类型(nullable type)转换为非空类型(non-null type)。
使用 !!
操作符时,Kotlin 编译器会假定该变量不为 null。如果该变量在运行时为 null,将抛出 KotlinNullPointerException
。
示例代码
假设有一个类 Experiment
,它包含一个可空类型的属性 flowSetting
,该属性又包含一个 stages
属性:
class FlowSetting(val stages: List<String>?)
class Experiment(val flowSetting: FlowSetting?)
以下是使用 !!
操作符的示例:
fun main() {
val experiment = Experiment(FlowSetting(listOf("Stage1", "Stage2", "Stage3")))
val stages = experiment.flowSetting!!.stages println(stages)
// 输出: [Stage1, Stage2, Stage3]
val experimentWithNullFlowSetting = Experiment(null)
val stagesWithNullFlowSetting = experimentWithNullFlowSetting.flowSetting!!.stages
// 这里会抛出 KotlinNullPointerException,因为 flowSetting 为 null }
解释
experiment.flowSetting!!
: 这个表达式表示非常确定flowSetting
不为 null。如果flowSetting
为 null,会抛出KotlinNullPointerException
。experiment.flowSetting!!.stages
: 在确保flowSetting
不为 null 之后,访问其stages
属性。
注意事项
使用 !!
操作符时需要非常小心,因为它可能会导致程序在运行时抛出 KotlinNullPointerException
。通常建议尽量避免使用 !!
,而是使用更安全的处理可空类型的方法,如安全调用操作符 ?.
、let
、run
等。
安全替代方案
-
安全调用操作符
?.
:val stages = experiment.flowSetting?.stages if (stages != null) { println(stages) } else { println("FlowSetting or stages is null") }
-
let
函数:experiment.flowSetting?.let { flowSetting -> val stages = flowSetting.stages println(stages) }
-
if
检查:if (experiment.flowSetting != null) { val stages = experiment.flowSetting!!.stages println(stages) } else { println("FlowSetting is null") }
示例程序
以下是一个更安全的示例,使用了安全调用操作符 ?.
和 let
函数:
class FlowSetting(val stages: List<String>?)
class Experiment(val flowSetting: FlowSetting?)
fun main() {
val experiment = Experiment(FlowSetting(listOf("Stage1", "Stage2", "Stage3")))
experiment.flowSetting?.let { flowSetting ->
val stages = flowSetting.stages println(stages)
// 输出: [Stage1, Stage2, Stage3] } ?: println("FlowSetting is null")
val experimentWithNullFlowSetting = Experiment(null)
experimentWithNullFlowSetting.flowSetting?.let { flowSetting ->
val stages = flowSetting.stages println(stages) } ?: println("FlowSetting is null")
// 输出: FlowSetting is null
}
这样可以避免潜在的 KotlinNullPointerException
,同时更安全地处理可空类型。