Я должен использовать двойной =
или тройной =
?
if(a === null) {
//do something
}
или
if(a == null) {
//do something
}
Аналогично для «не равно»:
if(a !== null) {
//do something
}
или
if(a != null) {
//do something
}
Я должен использовать двойной =
или тройной =
?
if(a === null) {
//do something
}
или
if(a == null) {
//do something
}
Аналогично для «не равно»:
if(a !== null) {
//do something
}
или
if(a != null) {
//do something
}
Ответы:
Оба подхода генерируют один и тот же байт-код, поэтому вы можете выбирать все, что вам больше нравится.
Структурное равенство a == b
переводится как
a?.equals(b) ?: (b === null)
Следовательно, при сравнении с null
, структурное равенство a == null
переводится в ссылочное равенство a === null
.
Согласно документам , нет смысла оптимизировать ваш код, поэтому вы можете использовать a == null
и a != null
обратите внимание, что если переменная является изменяемым свойством, вы не сможете интеллектуально преобразовать ее в ее тип, не допускающий значения NULL внутри if
оператора (потому что значение могло быть изменено другим потоком), и вам придется использовать let
вместо него безопасный оператор вызова .
Оператор безопасного звонка ?.
a?.let {
// not null do something
println(it)
println("not null")
}
Вы можете использовать его в сочетании с оператором Элвиса.
Оператор Элвиса ?:
(я предполагаю, потому что знак допроса похож на волосы Элвиса)
a ?: println("null")
И если вы хотите запустить блок кода
a ?: run {
println("null")
println("The King has left the building")
}
Сочетание двух
a?.let {
println("not null")
println("Wop-bop-a-loom-a-boom-bam-boom")
} ?: run {
println("null")
println("When things go null, don't go with them")
}
if
для нулевых проверок? a?.let{} ?: run{}
уместно только в редких случаях, иначе это не идиоматика
null
проверок, я перечислял другие жизнеспособные варианты. Хотя я не уверен, run
есть ли какое-то снижение производительности. Я обновлю свой ответ, чтобы было понятнее.
a
это a var
, то с использованием a?.let{} ?: run{}
гарантии, что он будет правильно привязан let
для всей области. Если a
есть val
, то разницы нет.
val
, то использование let отличается, и это плохо. Я нашел эту статью очень хорошей для объяснения этого - Kotlin: не используйте LET только для проверки нуля .
Безопасный доступ
val dialog : Dialog? = Dialog()
dialog?.dismiss() // if the dialog will be null,the dismiss call will be omitted
Пусть функция
user?.let {
//Work with non-null user
handleNonNullUser(user)
}
Ранний выход
fun handleUser(user : User?) {
user ?: return //exit the function if user is null
//Now the compiler knows user is non-null
}
Неизменяемые тени
var user : User? = null
fun handleUser() {
val user = user ?: return //Return if null, otherwise create immutable shadow
//Work with a local, non-null variable named user
}
Значение по умолчанию
fun getUserName(): String {
//If our nullable reference is not null, use it, otherwise use non-null value
return userName ?: "Anonymous"
}
Используйте val вместо var
val
доступен только для чтения, var
может изменяться. Рекомендуется использовать как можно больше свойств только для чтения, они ориентированы на многопоточность.
Используйте lateinit
Иногда нельзя использовать неизменяемые свойства. Например, это происходит на Android, когда при onCreate()
вызове инициализируется какое-то свойство . Для таких ситуаций в Kotlin есть языковая функция под названием lateinit
.
private lateinit var mAdapter: RecyclerAdapter<Transaction>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mAdapter = RecyclerAdapter(R.layout.item_transaction)
}
fun updateTransactions() {
mAdapter.notifyDataSetChanged()
}
Дополнение к @Benito Bertoli,
комбинация на самом деле не похожа на if-else
"test" ?. let {
println ( "1. it=$it" )
} ?: let {
println ( "2. it is null!" )
}
Результат:
1. it=test
Но если:
"test" ?. let {
println ( "1. it=$it" )
null // finally returns null
} ?: let {
println ( "2. it is null!" )
}
Результат:
1. it=test
2. it is null!
Также, если сначала использовать elvis:
null ?: let {
println ( "1. it is null!" )
} ?. let {
println ( "2. it=$it" )
}
Результат:
1. it is null!
2. it=kotlin.Unit
Ознакомьтесь с полезными методами, они могут быть полезны:
/**
* Performs [R] when [T] is not null. Block [R] will have context of [T]
*/
inline fun <T : Any, R> ifNotNull(input: T?, callback: (T) -> R): R? {
return input?.let(callback)
}
/**
* Checking if [T] is not `null` and if its function completes or satisfies to some condition.
*/
inline fun <T: Any> T?.isNotNullAndSatisfies(check: T.() -> Boolean?): Boolean{
return ifNotNull(this) { it.run(check) } ?: false
}
Ниже приведен возможный пример использования этих функций:
var s: String? = null
// ...
if (s.isNotNullAndSatisfies{ isEmpty() }{
// do something
}