使用 !! 是非常糟糕的做法吗?在科特林?
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
最近有一些关于是否!!应该在科特林代码中使用。一种意见是根本不应该使用它,因为这对 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