2

最近有一些讨论是否!应该在 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
}
4

4 回答 4

7

在这种情况下,有多种惯用的方式来表达这个想法而不使用!!,所以最好不要使用它。这是我要做的(使用Kotlin 1.3 中添加的orEmpty函数):

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

在其他情况下,它可能并不那么容易,所以没有绝对的规则说!绝对不能使用。然而,根据我们的经验,有很大比例的使用!! 在 IntelliJ 和 Kotlin 代码库中,最终会被我们的用户报告为运行时异常。

于 2018-12-20T05:27:27.390 回答
3

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

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
    }
}

但这可能只是我。

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

于 2018-12-20T01:19:25.253 回答
2

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

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

(此外,在这种情况下,您还可以进行两个进一步的更改:使用lateinitvar,它再次不需要任何!!; 并将整个条件替换为更简洁的.isNotNullOrEmpty()。)

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

于 2018-12-20T01:09:30.323 回答
0

我宁愿使用requireNotNull(). IllegalStateException如果参数是 则抛出null

于 2020-06-08T06:40:09.207 回答