¿No puedo entender qué ?:
hace en, por ejemplo, este caso
val list = mutableList ?: mutableListOf()
y por qué se puede modificar a este
val list = if (mutableList != null) mutableList else mutableListOf()
Esto se llama el operador Elvis y hace... Exactamente lo que has descrito en tu pregunta. Si su lado izquierdo es un valor null
, devuelve el lado derecho en su lugar, como una especie de respaldo. De lo contrario, simplemente devuelve el valor en el lado izquierdo.
a ?: b
es 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
Echemos un vistazo a la definición :
Cuando tenemos una referencia anulable r, podemos decir "si r no es nulo, úselo; de lo contrario, use algún valor x no nulo":
El operador ?:
(Elvis) evita la verbosidad y hace que su código sea realmente conciso.
Por ejemplo, muchas funciones de extensión de colección devuelven un null
como respaldo.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?:
le brinda una manera de manejar el caso alternativo de manera elegante, incluso si tiene varias capas de respaldo. Si es así, simplemente puede encadenar operadores multiplicadores de Elvis, 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 if else sería mucho más código que es más difícil de leer.
TL; DR: si la referencia de objeto resultante [primer operando] no es null
, se devuelve. De lo contrario, se devuelve el valor del segundo operando (que puede ser null
). Además, el operador puede generar una excepción si se devuelve un valor nulo.
El operador 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 Elvis
?:
es un operador binario que devuelve su primer operando si ese operando estrue
, y de lo contrario evalúa y devuelve su segundo operando. Es una variante del operador condicional ternario ,? :
, que se encuentra 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 es
null
, se devuelve. De lo contrario, se devuelve el valor del segundo operando (que puede sernull
). Si el segundo operando es nulo, el operador también puede lanzar una excepción.
Un ejemplo:
x ?: y // yields `x` if `x` is not null, `y` otherwise. x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
El Operador Elvis se representa con 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 conciso y funciona como tal:
Si el first operand
no es nulo , se devolverá. Si es nulo , se devolverá el second operand
. Esto se puede usar para garantizar que una expresión no devolverá un valor nulo, ya que proporcionará un valor no anulable 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 getPotentialNull
no es nulo, lo devolverá retrieveString
; Si es nulo, en su lugar se devolverá la segunda expresión "Secondary Not-Null String"
.
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
, como una expresión throw Exception
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.
Fuente: Wojda, I. Moskala, M. Desarrollo de Android con Kotlin. 2017. Packt Publishing
Simplemente podemos decir que tienes dos manos. ¿Quieres saber, tu mano izquierda está funcionando en este momento?. Si la mano izquierda no funciona, return
empty
, de lo contrario busy
Ejemplo para Java:
private int a; if(a != null){ println("a is not null, Value is: "+a) } else{ println("a is null") }
Ejemplo para Kotlin:
val a : Int = 5 val l : Int = if (a != null) a.length else "a is null"
Básicamente, si el lado izquierdo de Elvis devuelve nulo por algún motivo, en su lugar devuelve el lado derecho.
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".
Considere el siguiente ejemplo,
var myStr:String? = null //trying to find out length of myStr, but it could be null, so a null check can be put as, val len = if (myStr != null){ myStr.length } else{ -1 }
Usando el operador elvis , el código anterior se puede escribir en una sola línea
val len = myStr?.length ?: -1 // will return -1 if myStr is null else will return length
Además de lo que ya se ha dicho, hay un buen patrón que no era obvio para mí, pero que es común, por ejemplo, estás escribiendo una función larga, pero si algo es nulo , no tiene sentido continuar y lo único que puede hacer es regresar de la función. Normalmente escribirías
something = expression if (something == null) { return }
Con elvis se vuelve más corto y elegante:
something = expression ?: return
Sin embargo, una pequeña adición es esta
X = A ?: B
X
seguirá siendo null
si tanto A
como B
se evalúan como null
Por lo tanto, si desea que X
siempre sea non-null
, asegúrese de que B
siempre sea non-null
o que B
siempre se evalúe como non-null
si se trata de una función o expresión.
El operador elvis en Kotlin se usa para seguridad nula.
x = a ?: b
En el código anterior, a x
se le asignará el valor de a
si a no es null
y b
si a
es null
.
El código kotlin equivalente sin usar el operador elvis está a continuación:
x = if(a == null) b else a