Я не могу понять, что ?:
, например, в этом случае
val list = mutableList ?: mutableListOf()
и почему его можно изменить на это
val list = if (mutableList != null) mutableList else mutableListOf()
Я не могу понять, что ?:
, например, в этом случае
val list = mutableList ?: mutableListOf()
и почему его можно изменить на это
val list = if (mutableList != null) mutableList else mutableListOf()
Ответы:
TL; DR: Если результирующая ссылка на объект [первый операнд] не является null
, она возвращается. В противном случае null
возвращается значение второго операнда (которое может быть )
Оператор Elvis является частью многих языков программирования, например Kotlin, но также Groovy или C #. Я считаю определение Википедии довольно точным:
В некоторых языках компьютерного программирования оператор Элвиса
?:
- это бинарный оператор, который возвращает свой первый операнд, если этот операнд естьtrue
, а в противном случае оценивает и возвращает свой второй операнд. Это вариант тернарного условного оператора ,? :
найденного в этих языках (и во многих других): оператор Элвиса является тернарным оператором с опущенным вторым операндом .
Для Котлина особенно актуально следующее:
Некоторые языки программирования имеют разную семантику для этого оператора. Вместо того, чтобы первый операнд приводил к логическому значению, он должен приводить к ссылке на объект . Если результирующей ссылки на объект нет
null
, она возвращается. В противном случаеnull
возвращается значение второго операнда (которое может быть ).
Пример:
x ?: y // yields `x` if `x` is not null, `y` otherwise.
elvis operator
можно свести к чему-то другому. отлично! И хорошее объяснение, спасибо!
Элвис Оператор представлен знак вопроса следует двоеточие: ?:
и он может быть использован с этим синтаксисом:
first operand ?: second operand
Он позволяет вам писать целостный код и работает как таковой:
Если first operand
не null , он будет возвращен. Если он равен нулю , то second operand
будет возвращено. Это можно использовать, чтобы гарантировать, что выражение не вернет значение NULL, поскольку вы предоставите значение, не допускающее значения NULL, если предоставленное значение равно NULL.
Например (в Котлине):
fun retrieveString(): String { //Notice that this type isn't nullable
val nullableVariable: String? = getPotentialNull() //This variable may be null
return nullableVariable ?: "Secondary Not-Null String"
}
В этом случае, если вычисленное значение getPotentialNull
не равно нулю, оно будет возвращено retrieveString
; Если это ноль, второе выражение"Secondary Not-Null String"
вместо него будет возвращено .
Также обратите внимание, что выражение в правой части оценивается только в том случае, если левая часть равна нулю. .
В Kotlin вы можете использовать любое выражение second operand
, например, throw Exception
выражение
return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")
Имя Элвис Оператор происходит от известного американского певца Элвиса Пресли . Его прическа напоминает вопросительный знак.
Источник: Войда, И. Москала, М. Разработка Android с помощью Kotlin. 2017. Packt Publishing
Это называется оператором Элвиса, и он делает ... В точности то, что вы описали в своем вопросе. Если его левая сторона -null
значением, вместо этого он возвращает правую часть, что-то вроде запасного варианта. В противном случае он просто возвращает значение с левой стороны.
a ?: b
это просто сокращение от if (a != null) a else b
.
Еще несколько примеров с типами:
val x: String? = "foo"
val y: String = x ?: "bar" // "foo", because x was non-null
val a: String? = null
val b: String = a ?: "bar" // "bar", because a was null
a != null ? a : b
Давайте посмотрим на определение :
Когда у нас есть ссылка r, допускающая значение NULL, мы можем сказать: «Если r не равно NULL, используйте его, в противном случае используйте некоторое ненулевое значение x»:
Оператор ?:
(Элвис) позволяет избежать многословия и делает ваш код действительно кратким.
Например, многие функции расширения коллекции возвращаются null
как резервные.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?:
дает вам способ аккуратно справиться с резервным вариантом, даже если у вас есть несколько уровней отката. Если это так, вы можете просто связать операторы умножения Элвиса, как здесь:
val l = listOf(1, 2, 3)
val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")
Если бы вы выразили то же самое с помощью if else, было бы намного больше кода, который труднее читать.
Можно просто сказать, что у вас две руки. Вы хотите знать, работает ли ваша левая рука сейчас? Если левая рука не работает, return
empty
иначеbusy
Пример для Java:
private int a;
if(a != null){
println("a is not null, Value is: "+a)
}
else{
println("a is null")
}
Пример для Котлина:
val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
В принципе, если левая часть Элвиса по какой-то причине возвращает ноль, вместо этого возвращается правая сторона.
т.е.
val number: Int? = null
println(number ?: "Number is null")
Таким образом, если число НЕ равно нулю , оно напечатает число, иначе напечатает «Число равно нулю».
Оператор elvis в Котлине используется для нулевой безопасности.
x = a ?: b
В приведенном выше коде x
будет присвоено значение, a
если a не равно, null
а b
если a
есть null
.
Ниже приведен эквивалентный код котлина без использования оператора elvis:
x = if(a == null) b else a