使用 !! 是非常糟糕的做法吗?在科特林?

is it very bad practice using !! in kotlin?

最近有一些关于是否!!应该在科特林代码中使用。一种意见是根本不应该使用它,因为这对 kotlin 来说是一种不好的做法,会增加崩溃的风险。

另见感觉用!!不是绝对坏事,只要您知道在任何已知条件下,可空数据在该位置不应该为空,!!那里只是一个安全卫士(如果它在不应该出现的地方意外变为 null !! 会抓住它并引起关注,那么它肯定需要进行调查)。它不应该考虑使用!是崩溃的原因之一。

有没有人反对或赞成使用!! (不是盲目使用)?

下面两个样例,没看到dataCount_2会更好,还是?

var data: List<Data>? = null  // it will be set before calling the two dataCount()

fun dataCount_1() : Int {
    return if (data!=null && data!!.isNotEmpty())  data!![0].count else 0
}

fun dataCount_2() : Int {

    data?.let { dataList ->
        if (dataList.isNotEmpty()) {
            return dataList[0].count ?: 0
        }
    }
    return 0
}

我认为 dataCount_1() 中不需要任何 !!,因为在显式 null 检查之后,编译器知道 data 不能为 null 并智能转换为不可为 null 的类型。

因此,虽然在极少数情况下 !! 可能是合适的,但我认为这不是其中之一!

(此外,在这种情况下您还可以进行两个进一步的更改:使用 lateinit 变量,它同样不需要任何 !!;并用更多的条件替换整个条件简洁.isNotNullOrEmpty().)

总的来说,我的经验表明 大多数 的时间 !!,有更好的方法。但我不会完全禁止它:如果您仔细考虑了所有替代方案并且仍然认为 !! 是最清晰和最安全的方式,那么请继续。

其实在这种情况下,最简单和最安全的方法就是这样做:

var data: List<Data>? = null  // it will be set before calling the two dataCount()

fun dataCount() : Int {
    val data = data
    return when {
        data == null || data.isEmpty() -> 0
        else -> data[0].count
    }
}

虽然我个人只是使​​用 run 使其成为单行函数。

fun dataCount() : Int = run {
    val data = data
    when {
        data == null || data.isEmpty() -> 0
        else -> data[0].count
    }
}

但这可能只是我。

无论哪种方式,如果您将可变变量分配给 val(或者将其保存在闭包中,就像您在第二个示例中对 ?.let { 所做的那样),那么您可以利用智能转换你不需要使用 !!.

在这种情况下,有多种不使用 !! 的惯用表达方式,因此最好不要使用它。这是我会做的(使用 Kotlin 1.3 中添加的 orEmpty 函数):

fun dataCount() = data.orEmpty().firstOrNull()?.count ?: 0

在其他情况下,可能没那么容易,所以没有绝对的规定!!绝不能使用。但是,根据我们的经验,很大一部分使用 !!在 IntelliJ 和 Kotlin 代码库中最终被我们的用户报告为运行时异常。

我更愿意使用 requireNotNull()。如果参数是 null.

,则抛出 IllegalStateException