Utilisation de booléen? dans l'expression if


130

Si j'ai un nullable Boolean b, je peux faire la comparaison suivante en Java:

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

Dans Kotlin, je peux réaliser la même chose en utilisant l' !!opérateur:

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

Cependant, l'utilisation de !!me semble un peu sommaire, contournant le système de sécurité nul.

Y a-t-il une approche plus élégante pour cela?


Edit Il semble que j'ai un peu trop simplifié. Pour les variables locales, comme le montre Banthar , cela fonctionne. Cependant, mon booléen best en fait une "propriété avec un champ de sauvegarde" (je ne suis pas encore vraiment au courant de ce que cela impose). Voici le résultat:

entrez la description de l'image ici


Pourquoi avez-vous besoin !!bet pas simplement b? (Je ne connais pas très bien kotlin, juste des curiosités)
Maroun

1
@MarounMaroun Depuis bpeut être nullet l'une des fonctionnalités de Kotlin est Null Safety , qui donne des erreurs de compilation lors de la tentative d'évaluation de références Nullable. Ainsi, l'utilisation de plain bdonne une erreur de compilation :)
nhaarman

Mais vous ne vous b != nilattraperez pas avant de vérifier le bon côté?
Maroun

Vous diriez en effet, mais mon IDE dit le contraire. Je me souviens que quelque chose comme ça devrait marcher, je vais voir si je peux trouver quelque chose.
nhaarman

Je pense que cela val r = b?doSomething() ?: doSomethingElse()devrait fonctionner.
Maroun

Réponses:


184

Vous pouvez comparer avec booléenne annulable true, falseou en nullutilisant l' opérateur d'égalité:

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 
}

4
note: ne semble pas fonctionner avec l'opérateur inverse!
Richard

7
@Richard il aide à penser b comme ayant 3 valeurs possibles: true, falseou null. Ensuite, en faisant, if (b != true)vous savez seulement que b n'est pas vrai, mais vous ne savez rien sur falseounull
jivimberg

7
eg2. if (b != true) // b is null or falseeg3. if (b == false) // b is false
hmac le

C'est la bonne réponse et a du sens dans Kotlin, mais venant d'un arrière-plan Java, il peut sembler étrange de comparer explicitement à vrai ou faux ou nul dans une instruction if, ce qui peut expliquer pourquoi c'est une question et une réponse si populaire.
Michael Peterson

31

Si vous voulez vérifier proprement si un Boolean?est trueou falsevous pouvez faire:

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

Si vous voulez vérifier si c'est, nullvous pouvez ajouter cela (ou else) en tant que valeur dans le when:

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

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

22

Kotlin analysera statiquement vos vérifications nulles. C'est bon:

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

Même si cela échoue avec une erreur de type:

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

Pour plus d'informations, voir: http://kotlinlang.org/docs/reference/null-safety.html

Vous pouvez également utiliser un "opérateur de fusion nul" (qui fonctionnera pour les variables mutables):

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

L'analyse ne fonctionne que pour les valeurs immuables. Si vous devez le faire dans un champ mutable, stockez-le dans une variable locale temporaire.
Piotr Praszmo

1
Cela a du sens, en effet. L'opérateur de fusion nul est probablement ce que je recherchais. Merci!
nhaarman

@Banthar ce n'est pas tout à fait correct (votre deuxième exemple serait var?) ... s'il s'agit d'un local, varle compilateur peut toujours autoriser la conversion sécurisée. Pour des cas plus spéciaux, lisez stackoverflow.com/questions/34498562/…
Jayson Minard

null coalescing elvis peut être déplacé vers l'affectationval booleanVal = nullableProducer?.produceVal() ?: false; if (booleanVal) {}
Serge

6

D'après ce que j'ai vu le booléen? est le résultat d'une méthode qui retourne Boolean sur un objet qui est nullable

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

La solution que j'ai utilisée consiste à utiliser la letfonction pour supprimer la possible valeur nulle renvoyée comme suit

person?.let {
  if(it.isHome()) {
    //Do something
  }
}

5
Le premier se compile si vous remplacez ifblock par person?.isHome() == true.
Hesam

2

Dans Kotlin, vous pouvez faire comme ceci:

val b: Boolean? = true
if (b == true) { // if b is null, this should be null == true
    /* Do something */
} else {
    /* Do something else */
}

3
b != null && b == trueest le même que b == true.
nhaarman

1

tout d'abord, ajoutez la fonction en ligne personnalisée ci-dessous:

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
}

alors vous pouvez écrire un code comme celui-ci:

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

//or

b.ifFalse {
   /* Do something else in false case */
}

Oui, dans le cas: b.ifTrue {...} ou b.ifFalse {...} cela peut être utile
zyc zyc

1

Pour Kotlin, ce que j'utilise normalement est

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

cela ne fonctionnerait que lorsque la propriété est vraie et que l'objet n'est pas nul. Pour l'inverse:

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

0

Utilisons une if-elseinstruction avec un 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!")
}

// Résultat: "L'un d'eux n'est pas nullable ..."

a = null
b = null

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

// Résultat: "Les deux sont nullables!"


0

Il est assez facile d'ajouter une fonction d'extension si cela vous aide.

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

var x: Boolean? = null

if(x.orDefault()) {
..
}

0

Si vous souhaitez effectuer des opérations de la même manière containsur un, Stringvous pouvez utiliser le contrôle d'égalité comme ci-dessous

if (url?.contains("xxx") == true){
  return false;
}

-1

Vous pouvez faire avec un opérateur sûr "let"

val b: Boolean? = null
b?.let { flag ->
    if(flag){
        // true Block
    } else {
        // false Block
    }
}

Ce n'est tout simplement pas vrai et reviendra lors d'une exception levée.
nhaarman

Modification de ma réponse en fonction du commentaire précédent
finalpets
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.