O que faz?: Fazer em Kotlin? (Operador Elvis)

98

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()
Jocas
fonte
5
Retorne o lado esquerdo se não for nulo; caso contrário, retorne o lado direito. A primeira expressão é uma notação curta para a segunda expressão. kotlinlang.org/docs/reference/null-safety.html#elvis-operator
Eugen Pechanec

Respostas:

118

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 for truee, 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 ser null) é 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
s1m0nw1
fonte
3
Isso é muito legal. Nunca pensei que elvis operatorpudesse ser ainda mais reduzido a outra coisa. bom! E boa explicação, obrigado!
sud007
91

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 operandserá 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 getPotentialNullnã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 Exceptionexpressã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

Elvis QuestionMark

Fonte: Wojda, I. Moskala, M. Android Development with Kotlin. 2017. Packt Publishing

LeoColman
fonte
88
Mais 1 para ilustrar o Sr. Presley
s1m0nw1
7
? :) (veja como Elvis sorrindo)
LeoColman
1
Depois de um tempo, não consigo entender por que se chama Operador Elvis. Sua ilustração me fez saber por que se chama Operador Elvis. :)
Yohanes AI
a história sobre Elvis é realmente verdadeira? haha
Hillcow de
@Kerooker Ele não está sorrindo,?: | será melhor IMO.
ahmed galal
38

Isso é chamado de operador de Elvis e faz ... Exatamente o que você descreveu na sua pergunta. Se o lado esquerdo for um nullvalor, 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
zsmb13
fonte
11
se você vem de java, é mais uma abreviatura para:a != null ? a : b
crgarridos
9

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 nullcomo 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.

Willi Mentzel
fonte
3

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 emptysenã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"
Romman
fonte
Amei essa resposta. Muito limpo para entender.
Gk Mohammad Emon
2

Basicamente, se o lado esquerdo de Elvis retorna nulo por algum motivo, retorna o lado direito.

ie

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

Então, se número NÃO for nulo , ele imprimirá número, caso contrário , imprimirá "Número é nulo".

pauloaap
fonte
1

O operador elvis em Kotlin é usado para segurança nula.

x = a ?: b

No código acima, xserá atribuído o valor de aif a is not nulland bif aisnull .

O código kotlin equivalente sem usar o operador elvis está abaixo:

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

Uma pequena adição é esta

X = A ?: B

Xainda será nullse ambos Ae Bavaliaremnull

Portanto, se você quiser Xser sempre non-null, certifique-se de que Bé sempre um non-nullou que Bsempre avalia non-nullse é uma função ou expressão.

Wilson
fonte