Чи слід використовувати подвійний =чи потрійний =?
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
зауважте, що якщо змінна є властивістю, що змінюється, ви не зможете розумно передати її до її ненульованого типу всередині ifоператора (оскільки значення могло бути змінено іншим потоком), і letзамість цього вам доведеться використовувати оператор безпечного виклику .
Безпечний дзвінок оператора ?.
a?.let {
// not null do something
println(it)
println("not null")
}
Ви можете використовувати його в поєднанні з оператором Elvis.
Оператор Елвіса ?: (я здогадуюсь, бо знак допиту схожий на волосся Елвіса)
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є var, то, використовуючи a?.let{} ?: run{}гарантію, що він буде належним чином пов'язаний у letвсьому обсязі. Якщо aє a val, то різниці немає.
val, то використання let - це інше, і це погано. Я знайшов цю статтю дуже вдалою для її пояснення - Котлін: Не використовуйте просто 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є змінним. Рекомендується використовувати якомога більше властивостей лише для читання, вони безпечні для потоку.
Використовуйте латеніт
Іноді не можна використовувати незмінні властивості. Наприклад, це відбувається на Android, коли якесь властивість ініціалізується у onCreate()виклику. У цих ситуаціях Котлін має мовну функцію, яка називається 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
}