Я не могу понять, что ?:, например, в этом случае
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