¿Qué hace ?: hacer en Kotlin? (Operador de Elvis)

98

No puedo entender qué ?:hace, por ejemplo, en este caso.

val list = mutableList ?: mutableListOf() 

y por qué se puede modificar a esto

val list = if (mutableList != null) mutableList else mutableListOf()
Jocas
fuente
5
Regrese el lado izquierdo si no es nulo, de lo contrario, regrese el lado derecho. La primera expresión es una notación corta para la segunda expresión. kotlinlang.org/docs/reference/null-safety.html#elvis-operator
Eugen Pechanec

Respuestas:

115

TL; DR: Si la referencia del objeto resultante [primer operando] no nulllo es, se devuelve. De lo contrario, nullse devuelve el valor del segundo operando (que puede ser )


El operador de Elvis es parte de muchos lenguajes de programación, por ejemplo, Kotlin pero también Groovy o C #. Encuentro la definición de Wikipedia bastante precisa:

En ciertos lenguajes de programación de computadoras, el operador de Elvis ?: es un operador binario que devuelve su primer operando si ese operando es true, y de lo contrario evalúa y devuelve su segundo operando. Se trata de una variante del operador condicional ternario , ? :encontró en esos idiomas (y muchos otros): el operador Elvis es el operador ternario con su segundo operando omitido .

Lo siguiente es especialmente cierto para Kotlin:

Algunos lenguajes de programación de computadoras tienen una semántica diferente para este operador. En lugar de que el primer operando tenga que dar como resultado un booleano, debe dar como resultado una referencia de objeto . Si la referencia del objeto resultante no nulllo es, se devuelve. De lo contrario, nullse devuelve el valor del segundo operando (que puede ser ).

Un ejemplo:

x ?: y // yields `x` if `x` is not null, `y` otherwise.
s1m0nw1
fuente
3
Esto es realmente genial. Nunca pensé que elvis operatorpudiera reducirse más a otra cosa. ¡bonito! Y bonita explicación, ¡gracias!
sud007
88

El operador de Elvis está representado por un signo de interrogación seguido de dos puntos: ?:y se puede usar con esta sintaxis:

first operand ?: second operand

Le permite escribir un código coherente y funciona como tal:

Si first operand no es nulo , se devolverá. Si es nulo , second operandse devolverá. Esto se puede usar para garantizar que una expresión no devuelva un valor nulo, ya que proporcionará un valor que no acepta valores NULL si el valor proporcionado es nulo.


Por ejemplo (en Kotlin):

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

En este caso, si el valor calculado de getPotentialNullno es nulo, será devuelto por retrieveString; Si es nulo, "Secondary Not-Null String"se devolverá la segunda expresión .

También tenga en cuenta que la expresión del lado derecho se evalúa solo si el lado izquierdo es nulo .

En Kotlin, puede usar cualquier expresión como second operand, por ejemplo, una throw Exceptionexpresión

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

El nombre Elvis Operator proviene del famoso cantante estadounidense Elvis Presley . Su peinado se asemeja a un signo de interrogación.

Elvis QuestionMark

Fuente: Wojda, I. Moskala, M. Desarrollo de Android con Kotlin. 2017. Packt Publishing

LeoColman
fuente
84
Más 1 por ilustrar al señor Presley
s1m0nw1
7
? :) (verlo como Elvis sonriendo)
LeoColman
1
Después de un tiempo, no puedo entender por qué se llama Elvis Operator. Tu ilustración me hizo saber por qué se llama Elvis Operator. :)
Yohanes AI
¿Es realmente cierta la historia de Elvis? jaja
Hillcow
@Kerooker No está sonriendo,?: | será mejor en mi opinión.
Ahmed Galal
38

Esto se llama operador de Elvis y lo hace ... Exactamente lo que ha descrito en su pregunta. Si su lado izquierdo es un nullvalor, devuelve el lado derecho en su lugar, una especie de retroceso. De lo contrario, solo devuelve el valor en el lado izquierdo.

a ?: bes solo una abreviatura de if (a != null) a else b.

Algunos ejemplos más con tipos:

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
fuente
10
si vienes de Java, es más una abreviatura de:a != null ? a : b
crgarridos
9

Echemos un vistazo a la definición :

Cuando tenemos una referencia r anulable, podemos decir "si r no es nulo, utilícelo, de lo contrario use algún valor no nulo x":

los ?: operador (Elvis) evita la verbosidad y hace que su código sea realmente conciso.

Por ejemplo, muchas funciones de extensión de colección regresan nullcomo reserva.

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

?:le brinda una forma de manejar el caso de respaldo de manera elegante incluso si tiene varias capas de respaldo. Si es así, simplemente puede encadenar operadores de Elvis multiplicados, como aquí:

val l = listOf(1, 2, 3)

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

Si expresara lo mismo con si de lo contrario, sería mucho más código que es más difícil de leer.

Willi Mentzel
fuente
3

Simplemente podemos decir que tienes dos manos. Quieres saber si tu mano izquierda está funcionando en este momento ?. Si la mano izquierda no funciona, de lo return emptycontrariobusy

Ejemplo para Java:

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

Ejemplo de Kotlin:

val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
Romman
fuente
Amo esta respuesta. Demasiado limpio para entenderlo.
Gk Mohammad Emon
2

Básicamente, si el lado izquierdo de Elvis devuelve nulo por alguna razón, devuelve el lado derecho en su lugar.

es decir

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

Entonces, si el número NO es nulo , imprimirá el número; de lo contrario , imprimirá "El número es nulo".

pauloaap
fuente
1

El operador de elvis en Kotlin se utiliza para una seguridad nula.

x = a ?: b

En el código anterior, xse le asignará el valor de asi a no es nully bsi aes null.

El código de kotlin equivalente sin usar el operador de elvis está a continuación:

x = if(a == null) b else a
Abhishek A Udupa
fuente
1

Aunque una pequeña adición es esta

X = A ?: B

Xseguirá siendo nullsi ambos Ay Bevalúannull

Por lo tanto, si quiere Xser siempre non-null, asegúrese de Bque siempre sea un non-nullo que Bsiempre evalúe non-nullsi es una función o expresión.

Wilson
fuente