调用解构声明初始值设定项的 'component1()' 函数所需的不可空值

Not nullable value required to call 'component1()' function of destructuring declaration initializer

下面的代码可以用Kotlin编译吗?

val variable: String? = "string"

val (a, b) = variable?.run {
    1 to 2
}  

编译器不允许解构,因为右侧的表达式类型为可空 Pair<Int, Int>?,并且不清楚 ab 应该进入什么值case variable 为空。

为了解决这个问题,你需要在=之后得到一个非空表达式。

有很多不同的方法来处理可空值并从可空值生成非空值,请参阅:

例如,如果要为 ab 提供回退值,则使用 ?: 运算符,如下所示:

val (a, b) = variable?.run {
    1 to 2
} ?: (0 to 0)

例如,另一种方法是先检查 variable 是否为 null:

val (a, b) = checkNotNull(variable) { "variable should never be null" }.run {
    1 to 2
}

Null 没有任何解构声明。如果您希望 null 值像一对 null 一样解构,您可以添加这些扩展:

operator fun <T> Pair<T, *>?.component1() = this?.component1()
operator fun <T> Pair<*, T>?.component2() = this?.component2()

否则,如其他答案所示,您需要使用 Elvis 运算符提供默认值。

它不是自动的,因为它不知道你想要什么。根据您的用途,0 to 0 可能是最合适的,或者 -1 to -10 to nullnull to null.

问题是,如果你的变量为null,你想做什么?如果您想抛出异常,请按照@hotkey 的建议使用 requirecheck

但是,如果值为 null,我只想 return。所以我给自己写了一个小辅助函数来实现这个:

private inline fun <T> T?.exitIfNull(exitBlock: () -> Nothing): T {
    if (this == null)
        exitBlock()
    else
        return this
}

您可以按如下方式调用此函数:

val (a, b) = variable?.run {
    1 to 2
}.exitIfNull {
    return
}

Kotlin 中 Nothing 关键字的一个很好的小用法,我个人觉得非常有趣