Это очень плохая практика использования! в котлин?
Недавно была дискуссия о том, является ли!! следует использовать в коде kotlin. Одно мнение, что это не следует использовать вообще, потому что это плохая практика с kotlin и увеличивает риск аварии.
Другое мнение чувствует себя с помощью!! это не совсем плохая вещь, если вы знаете, что обнуляемые данные не должны быть нулевыми в любом месте при любом известном условии!! там просто охранник (если он неожиданно станет нулевым в том месте, где его не должно быть! он поймает его и вызовет беспокойство, тогда его обязательно нужно исследовать). Это не должно рассмотреть использование!! это одна из причин аварии.
Кто-нибудь имеет мнение против или против использования!! (не использовать его вслепую)?
два примера ниже, не видите 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
}
3 ответа
В этом случае есть несколько идиоматических способов выразить идею без использования !!
так что определенно предпочтительнее не использовать его. Вот что я хотел бы сделать (используя функцию orEmpty, добавленную в Kotlin 1.3):
fun dataCount() = data.orEmpty().firstOrNull()?.count ?: 0
В других случаях это может быть не так просто, поэтому не существует абсолютного правила, говорящего об этом!! никогда не должен использоваться. Однако, по нашему опыту, значительный процент использования!! в IntelliJ и Kotlin кодовые базы в конечном итоге сообщаются нашими пользователями как исключения.
На самом деле в этом случае самый простой и безопасный способ - сделать это так:
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 {
во втором примере), то вы можете использовать смарт-кастинг, и вам не нужно будет использовать !!
,
Я не думаю что-либо !!
необходимы в dataCount_1()
, как после явной проверки нуля, компилятор знает data
не может быть нулевым и умным приведением к необнуляемому типу.
Так что пока есть очень мало случаев, когда !!
может быть уместно, я не думаю, что это один из них!
(Кроме того, в этом случае вы можете внести еще два изменения: использовать lateinit
Вар, который снова не понадобится !!
; и заменить все условие более кратким .isNotNullOrEmpty()
.)
В целом мой опыт показывает, что большую часть времени вы достигаете !!
есть лучший подход. Но я бы не запретил это полностью: если вы тщательно рассмотрели все альтернативы и все еще думаете, что !!
самый ясный и безопасный путь, тогда иди вперед.
Я бы предпочел использовать requireNotNull()
. БроскиIllegalStateException
если аргумент null
.