Uso de booleano? em se expressão

130

Se eu tiver um valor nulo Boolean b, posso fazer a seguinte comparação em Java:

Boolean b = ...;
if (b != null && b) {
   /* Do something */
} else {
   /* Do something else */
}

No Kotlin, posso obter o mesmo usando o !!operador:

val b: Boolean? = ...
if (b != null && b!!) {
   /* Do something */
} else {
   /* Do something else */
}

No entanto, o uso de me !!parece um pouco superficial, contornando o sistema de segurança nulo.

Existe uma abordagem mais elegante para isso?


Editar Parece que eu simplifiquei um pouco demais. Para variáveis ​​locais, como mostra Banthar , funciona. No entanto, meu booleano bé na verdade uma "propriedade com um campo de apoio" (não estou realmente atualizado ainda sobre o que isso impõe). Este é o resultado:

insira a descrição da imagem aqui

nhaarman
fonte
Por que você precisa !!be não simplesmente b? (Eu não sou tão familiarizado com Kotlin, apenas curiosidades)
Maroun
1
@MarounMaroun Desde que bpode ser nulle um dos recursos do Kotlin é o Null Safety , que fornece erros de compilação ao tentar avaliar referências anuláveis. Assim, usando simples bdá um erro de compilação :)
nhaarman
Mas não b != nilentenderá isso antes de verificar o lado direito?
Maron
Você diria que sim, mas meu IDE diz o contrário. Eu lembro que algo assim deveria funcionar, vou ver se consigo encontrar alguma coisa.
Nhaarman 28/09/2015
Eu acho que val r = b?doSomething() ?: doSomethingElse()deveria funcionar.
Maroun 28/09

Respostas:

183

Você pode comparar booleano anulável com true, falseou nullutilizando operador de igualdade:

var b: Boolean? = null
if (b == true) {
    // b was not null and equal true
} 
if (b == false) {
   // b is false 
}
if (b != true) { 
   // b is null or false 
}
Ilya
fonte
4
nota: não parece trabalho com o operador inverso!
Richard
7
@ Richard ele ajuda a pensar b como um com 3 valores possíveis: true, falseou null. Em seguida, ao fazer if (b != true)você só sabe que b não é verdade, mas você não sabe nada sobre falseounull
jivimberg
7
eg2. if (b != true) // b is null or falseeg3. if (b == false) // b is false
hmac
Essa é a resposta correta e faz sentido no Kotlin, mas, vindo de um plano Java, pode parecer estranho comparar explicitamente com verdadeiro, falso ou nulo em uma instrução if, o que pode explicar por que essa é uma pergunta e resposta tão popular.
22419 Michael Peterson #
31

Se você deseja verificar corretamente se um Boolean?é trueou falsepode:

when(b) {
    true -> {}
    false -> {}
}

Se você quiser verificar se é nullpossível, pode adicionar isso (ou else) como um valor no when:

when(b) {
    true -> {}
    false -> {}
    null -> {}
}

when(b) {
    true -> {}
    false -> {}
    else-> {}
}
Eliezer
fonte
22

O Kotlin analisará estaticamente suas verificações nulas. Isto é bom:

val b: Boolean? = null
if (b != null && b) {
    println(b)
}

Mesmo que isso falhe com o erro de tipo:

val b: Boolean? = null
if (b == null && b) {
    println(b)
}

Para mais informações, consulte: http://kotlinlang.org/docs/reference/null-safety.html

Você também pode usar o "operador coalescente nulo" (que funcionará para variáveis ​​mutáveis):

val b: Boolean? = null
if (b ?: false) {
    println(b)
}
Piotr Praszmo
fonte
A análise funciona apenas para valores imutáveis. Se você precisar fazer isso em um campo mutável, armazene-o na variável local temporária.
Piotr Praszmo 28/09/2015
1
Isso faz sentido, de fato. O operador coalescente nulo é provavelmente o que eu estava procurando. Obrigado!
Nhaarman 28/09/2015
@Banthar que não está completamente correto (seu segundo exemplo seria var?) ... se for um local var, o compilador ainda pode permitir a transmissão segura. Para casos mais especiais, leia stackoverflow.com/questions/34498562/…
Jayson Minard 6/16
elvis coalescente nulo pode ser movido para atribuiçãoval booleanVal = nullableProducer?.produceVal() ?: false; if (booleanVal) {}
Serge
6

Pelo que eu vi o booleano? é o resultado de um método que retorna Booleano em um objeto que é anulável

val person: Person? = null
....
if(person?.isHome()) { //This won't compile because the result is Boolean?
  //Do something
}

A solução que estou usando é usar a letfunção para remover o possível valor nulo retornado dessa forma

person?.let {
  if(it.isHome()) {
    //Do something
  }
}
DroidT
fonte
5
O primeiro compila se você substituir o ifbloco por person?.isHome() == true.
Hesam 23/01
2

No Kotlin, você pode fazer assim:

val b: Boolean? = true
if (b == true) { // if b is null, this should be null == true
    /* Do something */
} else {
    /* Do something else */
}
ininmm
fonte
3
b != null && b == trueé o mesmo que b == true.
nhaarman
1

primeiro, adicione a função embutida personalizada abaixo:

inline fun Boolean?.ifTrue(block: Boolean.() -> Unit): Boolean? {
    if (this == true) {
        block()
    }
    return this
}

inline fun Boolean?.ifFalse(block: Boolean?.() -> Unit): Boolean? {
    if (null == this || !this) {
        block()
    }

    return this
}

então você pode escrever um código como este:

val b: Boolean? = ...
b.ifTrue {
   /* Do something in true case */
}

//or

b.ifFalse {
   /* Do something else in false case */
}
zyc zyc
fonte
Sim, no caso: b.ifTrue {...} ou b.ifFalse {...} é pode ser útil
ZYC ZYC
1

Para Kotlin, o que eu normalmente uso é

if (object?.booleanProperty ==true)
   { 
     //do stuff 
   }

isso funcionaria apenas quando a propriedade for verdadeira e o objeto não for nulo. Pelo contrário:

if (!object?booleanProperty !=true)
   { 
     //do Stuff
   }
John
fonte
0

Vamos usar uma if-elsedeclaração com um Elvis Operator:

val a: Boolean?
val b: Boolean?

a = true
b = null

if (a != null ?: b) { 
    println("One of them isn't nullable...")
} else {
    println("Both are nullables!")
}

// Resultado: "Um deles não é anulável ..."

a = null
b = null

if (a != null ?: b) { 
    println("One of them isn't nullable...")
} else {
    println("Both are nullables!")
}

// Resultado: "Ambos são anuláveis!"

Andy Fedoroff
fonte
0

É muito fácil adicionar uma função de extensão, se isso o ajudar.

fun Boolean?.orDefault(default: Boolean = false): Boolean {
    if (this == null)
        return default
    return this
}

var x: Boolean? = null

if(x.orDefault()) {
..
}
Nic Bell
fonte
0

Caso você queira executar operações da mesma containforma, Stringuse a verificação de igualdade como abaixo -

if (url?.contains("xxx") == true){
  return false;
}
Anoop M
fonte
-1

Você pode fazer com o operador seguro "let"

val b: Boolean? = null
b?.let { flag ->
    if(flag){
        // true Block
    } else {
        // false Block
    }
}
finalpets
fonte
Isso simplesmente não é verdade e retornará em uma exceção lançada.
Nhaarman 16/11/19
Editou minha resposta com base no comentário anterior
finalpets 21/11/19