Eu não consigo descobrir o que ?:
, por exemplo, neste caso
val list = mutableList ?: mutableListOf()
e por que pode ser modificado para este
val list = if (mutableList != null) mutableList else mutableListOf()
Eu não consigo descobrir o que ?:
, por exemplo, neste caso
val list = mutableList ?: mutableListOf()
e por que pode ser modificado para este
val list = if (mutableList != null) mutableList else mutableListOf()
Respostas:
TL; DR: Se a referência do objeto resultante [primeiro operando] não for null
, ele será retornado. Caso contrário, o valor do segundo operando (que pode ser null
) é retornado. Além disso, o operador pode lançar uma exceção se null for retornado.
O operador Elvis faz parte de muitas linguagens de programação, por exemplo, Kotlin, mas também Groovy ou C #. Acho a definição da Wikipedia bastante precisa:
Em certas linguagens de programação de computador, o operador Elvis
?:
é um operador binário que retorna seu primeiro operando se esse operando fortrue
e, caso contrário, avalia e retorna seu segundo operando. É um variante do operador condicional ternário ,? :
, encontrados nessas línguas (e muitos outros): o operador Elvis é o operador ternário com o seu segundo operando omitido .
O seguinte é especialmente verdadeiro para Kotlin:
Algumas linguagens de programação de computador têm semânticas diferentes para este operador. Em vez de o primeiro operando ter que resultar em um booleano, ele deve resultar em uma referência de objeto . Se a referência do objeto resultante não for
null
, ela será retornada. Caso contrário, o valor do segundo operando (que pode sernull
) é retornado. Se o segundo operando for nulo, o operador também poderá lançar uma exceção.
Um exemplo:
x ?: y // yields `x` if `x` is not null, `y` otherwise.
x ?: throw SomeException() // yields `x` if `x` is not null, throws SomeException otherwise
elvis operator
pudesse ser ainda mais reduzido a outra coisa. bom! E boa explicação, obrigado!
O Operador Elvis é representado por um ponto de interrogação seguido de dois pontos: ?:
e pode ser usado com esta sintaxe:
first operand ?: second operand
Ele permite que você escreva um código consistente e funciona como tal:
Se first operand
não for nulo , ele será retornado. Se for nulo , o second operand
será retornado. Isso pode ser usado para garantir que uma expressão não retorne um valor nulo, pois você fornecerá um valor não anulável se o valor fornecido for nulo.
Por exemplo (em 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"
}
Nesse caso, se o valor calculado de getPotentialNull
não for nulo, ele será retornado por retrieveString
; Se for nulo, a segunda expressão "Secondary Not-Null String"
será retornada.
Observe também que a expressão do lado direito é avaliada apenas se o lado esquerdo for nulo .
No Kotlin, você pode usar qualquer expressão como second operand
, como uma throw Exception
expressão
return nullVariable ?: throw IllegalResponseException("My inner function returned null! Oh no!")
O nome Elvis Operator vem do famoso cantor americano Elvis Presley . Seu penteado lembra um ponto de interrogação
Fonte: Wojda, I. Moskala, M. Android Development with Kotlin. 2017. Packt Publishing
Isso é chamado de operador de Elvis e faz ... Exatamente o que você descreveu na sua pergunta. Se o lado esquerdo for um null
valor, ele retornará o lado direito, como uma espécie de fallback. Caso contrário, ele apenas retorna o valor do lado esquerdo.
a ?: b
é apenas uma abreviação de if (a != null) a else b
.
Mais alguns exemplos com 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
a != null ? a : b
Vamos dar uma olhada na definição :
Quando temos uma referência anulável r, podemos dizer "se r não é nulo, use-o, caso contrário, use algum valor não nulo x":
o ?:
operador (Elvis) evita o detalhamento e torna seu código realmente conciso.
Por exemplo, muitas funções de extensão de coleção retornam null
como fallback.
listOf(1, 2, 3).firstOrNull { it == 4 } ?: throw IllegalStateException("Ups")
?:
oferece uma maneira de lidar com o caso de fallback de forma elegante, mesmo se você tiver várias camadas de fallback. Nesse caso, você pode simplesmente multiplicar em cadeia os operadores Elvis, como aqui:
val l = listOf(1, 2, 3)
val x = l.firstOrNull { it == 4 } ?: l.firstOrNull { it == 5 } ?: throw IllegalStateException("Ups")
Se você expressasse o mesmo com senão, haveria muito mais código e seria mais difícil de ler.
Podemos simplesmente dizer que você tem duas mãos. Você quer saber, sua mão esquerda está trabalhando agora? Se a mão esquerda não funcionar, return
empty
senãobusy
Exemplo para Java:
private int a;
if(a != null){
println("a is not null, Value is: "+a)
}
else{
println("a is null")
}
Exemplo para Kotlin:
val a : Int = 5
val l : Int = if (a != null) a.length else "a is null"
O operador elvis em Kotlin é usado para segurança nula.
x = a ?: b
No código acima, x
será atribuído o valor de a
if a is not null
and b
if a
isnull
.
O código kotlin equivalente sem usar o operador elvis está abaixo:
x = if(a == null) b else a