Чи слід використовувати подвійний =
чи потрійний =
?
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
}