Co robi?: Robić w Kotlinie? (Operator Elvisa)

98

Nie mogę dowiedzieć się, co ?:robi na przykład w tym przypadku

val list = mutableList ?: mutableListOf() 

i dlaczego można go zmodyfikować do tego

val list = if (mutableList != null) mutableList else mutableListOf()
Jocas
źródło
5
Zwróć lewą stronę, jeśli nie jest zerowa, w przeciwnym razie wróć prawą stronę. Pierwsze wyrażenie to krótka notacja drugiego wyrażenia. kotlinlang.org/docs/reference/null-safety.html#elvis-operator
Eugen Pechanec

Odpowiedzi:

118

TL; DR: Jeśli wynikowe odwołanie do obiektu [pierwszy operand] nie jest null, jest zwracane. W przeciwnym razie zwracana jest wartość drugiego operandu (który może być null). Ponadto operator może zgłosić wyjątek, jeśli zostanie zwrócona wartość null.


Operator Elvis jest częścią wielu językach programowania, np Kotlin ale także Groovy lub C #. Uważam, że definicja z Wikipedii jest całkiem dokładna:

W niektórych językach programowania komputerowego operator Elvisa ?: jest operatorem binarnym, który zwraca swój pierwszy operand, jeśli tym operandem jest true, aw przeciwnym razie oblicza i zwraca drugi operand. Jest to wariant potrójnego operatora warunkowego , ? :, znalezionych w tych językach (i wielu innych): operator Elvis jest trójskładnikowych operatora z drugim argumencie pominięte .

Poniższe jest szczególnie prawdziwe w przypadku Kotlina:

Niektóre języki programowania komputerów mają inną semantykę dla tego operatora. Zamiast pierwszego operandu, który musi skutkować wartością logiczną, musi skutkować odwołaniem do obiektu . Jeśli wynikowe odwołanie do obiektu nie jest null, jest zwracane. W przeciwnym razie zwracana jest wartość drugiego operandu (który może być null). Jeśli drugi operand ma wartość null, operator może również zgłosić wyjątek.

Przykład:

x ?: y // yields `x` if `x` is not null, `y` otherwise.
x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
s1m0nw1
źródło
3
To jest naprawdę fajne. Nigdy nie myślałem, że elvis operatormożna jeszcze bardziej zredukować do czegoś innego. miły! I miłe wyjaśnienie, dziękuję!
sud007
91

Elvis Operator reprezentowany jest przez znak zapytania a następnie dwukropek: ?:i może być używany z tej składni:

first operand ?: second operand

Umożliwia pisanie kodu konsensusowego i działa tak:

Jeśli first operand nie jest null , zostanie zwrócona. Jeśli jest zerowa , second operandzostanie zwrócona. Może to służyć do zagwarantowania, że ​​wyrażenie nie zwróci wartości null, ponieważ podasz wartość niepodlegającą wartości null, jeśli podana wartość jest równa null.


Na przykład (w Kotlinie):

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"
}

W tym przypadku, jeśli obliczona wartość getPotentialNullnie jest zerowa, zostanie zwrócona przez retrieveString; Jeśli ma wartość null, "Secondary Not-Null String"zamiast tego zostanie zwrócone drugie wyrażenie .

Należy również zauważyć, że wyrażenie po prawej stronie jest oceniane tylko wtedy, gdy po lewej stronie jest null .

W Kotlinie możesz użyć dowolnego wyrażenia jako second operand, takiego jak throw Exceptionwyrażenie

return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")

Nazwa Elvis Operator pochodzi od słynnego amerykańskiego piosenkarza Elvisa Presleya . Jego fryzura przypomina znak zapytania

Elvis QuestionMark

Źródło: Wojda, I. Moskala, M. Android Development z Kotlin. 2017. Packt Publishing

LeoColman
źródło
88
Plus 1 za zilustrowanie pana Presleya
s1m0nw1
7
? :) (zobacz to jako uśmiechnięty Elvis)
LeoColman
1
Po chwili nie mogę zrozumieć, dlaczego nazywa się Elvis Operator. Twoja ilustracja pokazała mi, dlaczego nazywa się Elvis Operator. :)
Yohanes AI
czy historia o Elvisie jest prawdziwa? haha
Hillcow
@Kerooker Nie uśmiecha się,?: | będzie lepsza IMO.
ahmed galal
38

Nazywa się to operatorem Elvisa i robi ... Dokładnie to, co opisałeś w swoim pytaniu. Jeśli jego lewa strona jest nullwartością, zwraca zamiast tego prawą stronę, jako rezerwę. W przeciwnym razie zwraca tylko wartość po lewej stronie.

a ?: bjest po prostu skrótem if (a != null) a else b.

Więcej przykładów z typami:

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
zsmb13
źródło
11
jeśli pochodzisz z javy, jest to bardziej skrót od:a != null ? a : b
crgarridos
9

Spójrzmy na definicję :

Kiedy mamy odwołanie r dopuszczające wartość null, możemy powiedzieć „jeśli r nie jest null, użyj go, w przeciwnym razie użyj wartości x niezerowej”:

Operator ?:(Elvis) unika szczegółowości i sprawia, że ​​kod jest naprawdę zwięzły.

Na przykład wiele funkcji rozszerzających kolekcję zwraca nulljako rezerwę.

listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")

?:daje sposób na obsługę przypadku awaryjnego, nawet jeśli masz wiele warstw rezerwy. Jeśli tak, możesz po prostu połączyć w łańcuch multi operatorów Elvisa, jak tutaj:

val l = listOf(1, 2, 3)

val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")

Jeśli wyrazisz to samo za pomocą if else, będzie to dużo więcej kodu, który jest trudniejszy do odczytania.

Willi Mentzel
źródło
3

Po prostu możemy powiedzieć, że masz dwie ręce. Chcesz wiedzieć, czy twoja lewa ręka pracuje teraz? Jeżeli lewa ręka nie działa, return emptyinnybusy

Przykład dla Java:

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

Przykład dla Kotlina:

val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
Romman
źródło
Uwielbiam tę odpowiedź. Zbyt czysty, by to zrozumieć.
Gk Mohammad Emon,
2

Zasadniczo, jeśli lewa strona Elvisa z jakiegoś powodu zwraca wartość null, zamiast tego zwraca prawą stronę.

to znaczy

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

Tak więc, jeśli liczba NIE jest null , wypisze liczbę, w przeciwnym razie wypisze „Number is null”.

pauloaap
źródło
2

Operator elvis w Kotlin służy do zerowego bezpieczeństwa.

x = a ?: b

W powyższym kodzie xzostanie przypisana wartość, ajeśli a nie jest nulli bjeśli ajest null.

Odpowiedni kod kotlin bez użycia operatora elvis jest poniżej:

x = if(a == null) b else a
Abhishek A Udupa
źródło
1

Jest to jednak mały dodatek

X = A ?: B

Xnadal będzie, nulljeśli oba Ai Boceniająnull

Dlatego jeśli chcesz Xzawsze być non-null, upewnij się, że Bzawsze jest a non-nulllub, które Bzawsze non-nullzwraca wartość, jeśli jest to funkcja lub wyrażenie.

Wilson
źródło