Должен ли я использовать double =
или triple =
?
if(a === null) {
//do something
}
или
if(a == null) {
//do something
}
Аналогично для 'не равно':
if(a !== null) {
//do something
}
или
if(a != null) {
//do something
}
Должен ли я использовать double =
или triple =
?
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
.
В соответствии с docs нет смысла оптимизировать ваш код, поэтому вы можете использовать a == null
и a != 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")
}
Операция безопасного доступа
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
}