Що робить?: Робити в Котліні? (Оператор Елвіса)


98

Я не можу зрозуміти, що ?:робить, наприклад, у цьому випадку

val list = mutableList ?: mutableListOf() 

і чому його можна модифікувати до цього

val list = if (mutableList != null) mutableList else mutableListOf()

5
Поверніть ліву сторону, якщо вона не нульова, інакше поверніть праву сторону. Перший вираз - це короткі позначення для другого виразу. kotlinlang.org/docs/reference/null-safety.html#elvis-operator
Eugen Pechanec

Відповіді:


115

TL; DR: Якщо отримане посилання на об'єкт [перший операнд] немає null, воно повертається. В іншому випадку nullповертається значення другого операнда (яке може бути )


Оператор Елвіса є частиною багатьох мов програмування, наприклад Kotlin, але також Groovy або C #. Я вважаю визначення Вікіпедії досить точним:

У деяких мовах комп'ютерного програмування оператор Елвіса ?: - це двійковий оператор, який повертає свій перший операнд, якщо цей операнд є true, а в іншому випадку обчислює та повертає свій другий операнд. Це варіант трійкового умовного оператора , що ? :зустрічається в цих мовах (та багатьох інших): оператор Елвіса є потрійним оператором, а другий операнд опущений .

Для Котліна особливо справедливо наступне:

Деякі мови комп’ютерного програмування мають різну семантику для цього оператора. Замість того, щоб перший операнд мав приводити до логічного значення, він повинен приводити до посилання на об'єкт . Якщо отримане посилання на об'єкт немає null, воно повертається. В іншому випадку nullповертається значення другого операнда (яке може бути ).

Приклад:

x ?: y // yields `x` if `x` is not null, `y` otherwise.

3
Це справді круто. Я ніколи не думав, що це elvis operatorможе бути зведене до чогось іншого. приємно! І приємне пояснення, дякую!
sud007

88

Елвіс Оператор представлений знак питання слід двокрапка: ?:і він може бути використаний з цим синтаксисом:

first operand ?: second operand

Це дозволяє вам написати код консисею і працює як такий:

Якщо first operand значення не має значення null , його буде повернено. Якщо воно має значення null , тоді second operandбуде повернуто. Це може бути використано для гарантування того, що вираз не поверне нульового значення, оскільки ви надасте ненульоване значення, якщо надане значення є нульовим.


Наприклад (у Котліні):

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!")

Назва Elvis Operator походить від відомого американського співака Елвіса Преслі . Його зачіска нагадує знак запитання

Елвіс Питання

Джерело: Wojda, I. Moskala, M. Android Development with Kotlin. 2017. Видавництво Packt


84
Плюс 1 для ілюстрації містера Преслі
s1m0nw1

7
? :) (побачити це як Елвіс, що посміхається)
ЛеоКолман,

1
Через деякий час я не можу зрозуміти, чому його називають Elvis Operator. Ваша ілюстрація дала мені зрозуміти, чому її називають Елвісом Оператором. :)
Йоханес А.І.

правда історія про Елвіса? ха-ха
Hillcow,

@Kerooker Він не посміхається,?: | буде краще IMO.
Ahmed Galal,

38

Це називається оператором Елвіса, і він робить ... Саме те, що ви описали у своєму питанні. Якщо його ліва сторона є 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

10
якщо ви a != null ? a : b
походите

9

Давайте подивимося на Defintion :

Коли ми маємо нульове посилання r, ми можемо сказати "якщо r не є нульовим, використовуйте його, інакше використовуйте якесь ненульове значення 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")

Якщо ви висловите те саме, якщо інакше, це буде набагато більше коду, який важче читати.


3

Просто ми можемо сказати це, у вас дві руки. Ви хочете знати, чи працює зараз ваша ліва рука ?. Якщо ліва рука не працює, return emptyінакшеbusy

Приклад для Java:

private int a;
if(a != null){
    println("a is not null, Value is: "+a)
}
else{
    println("a is null")
}

Приклад для Kotlin:

val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"

Люблю цю відповідь. Занадто багато чистого, щоб зрозуміти.
Gk Mohammad Emon

2

В основному, якщо ліва частина Елвіса з якихось причин повертає значення null, замість цього повертає праву.

тобто

val number: Int? = null
println(number ?: "Number is null")

Отже, якщо число НЕ має значення null , воно надрукує номер, інакше надрукує "Number is null".


1

Оператор елвіса в Котліні використовується для нульової безпеки.

x = a ?: b

У наведеному вище коді xбуде присвоєно значення, aякщо a немає, nullа bякщо aє null.

Еквівалентний код kotlin без використання оператора elvis наведено нижче:

x = if(a == null) b else a

1

Хоча це невелике доповнення

X = A ?: B

Xвсе одно буде, nullякщо обидва Aі Bоцінитиnull

Тому, якщо ви хочете Xбути завжди non-null, переконайтесь, що Bце завжди non-nullабо що Bзавжди оцінює, non-nullчи це функція чи вираз.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.