Verwendung von Boolean? in if Ausdruck

130

Wenn ich eine Nullable habe Boolean b, kann ich den folgenden Vergleich in Java durchführen:

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

In Kotlin kann ich dasselbe erreichen, indem ich den !!Operator verwende:

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

Die Verwendung von !!fühlt sich für mich jedoch etwas skizzenhaft an und umgeht das Null-Sicherheitssystem.

Gibt es dafür einen eleganteren Ansatz?


Bearbeiten Es scheint, ich habe ein bisschen zu stark vereinfacht. Für lokale Variablen funktioniert es , wie Banthar zeigt. Mein Boolescher Wert bist jedoch tatsächlich eine "Eigenschaft mit einem Hintergrundfeld" (ich bin noch nicht wirklich auf dem neuesten Stand, was dies bedeutet). Das ist das Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Nhaarman
quelle
Warum brauchst du !!bund nicht einfach b? (Ich bin nicht so vertraut mit Kotlin, nur Kuriositäten)
Maroun
1
@MarounMaroun Da bmöglicherweise nullund eine der Funktionen von Kotlin ist Null Safety , die Kompilierungsfehler beim Versuch, nullfähige Referenzen auszuwerten, verursacht. Daher führt die Verwendung von plain zu beinem Kompilierungsfehler :)
nhaarman
Aber wird das nicht verstanden b != nil, bevor die rechte Seite überprüft wird?
Maroun
Sie würden zwar sagen, aber meine IDE sagt etwas anderes. Ich erinnere mich, dass so etwas funktionieren sollte, ich werde sehen, ob ich etwas finden kann.
Nhaarman
Ich denke val r = b?doSomething() ?: doSomethingElse()sollte funktionieren.
Maroun

Antworten:

183

Sie können auf NULL festlegbare boolean mit vergleichen true, falseoder nullunter Verwendung von Gleichheitsoperator:

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
quelle
4
Hinweis: scheint nicht mit dem inversen Operator zu funktionieren!
Richard
7
@ Richard hilft es , b als mit 3 möglichen Werten zu denken: true, falseoder null. Dann if (b != true)wissen Sie nur, dass b nicht wahr ist, aber Sie wissen nichts über falseodernull
jivimberg
7
eg2. if (b != true) // b is null or falseeg3. if (b == false) // b is false
hmac
Dies ist die richtige Antwort und macht in Kotlin Sinn, aber aus einem Java-Hintergrund heraus mag es seltsam sein, innerhalb einer if-Anweisung explizit mit wahr oder falsch oder null zu vergleichen, was möglicherweise erklärt, warum dies eine so beliebte Frage und Antwort ist.
Michael Peterson
31

Wenn Sie sauber prüfen möchten, ob a Boolean?ist trueoder falseSie Folgendes tun können:

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

Wenn Sie überprüfen möchten, ob dies der Fall ist, können nullSie dies (oder else) als Wert in Folgendes einfügen when:

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

when(b) {
    true -> {}
    false -> {}
    else-> {}
}
Elieser
quelle
22

Kotlin analysiert Ihre Nullprüfungen statisch. Das ist in Ordnung:

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

Auch wenn dies mit einem Typfehler fehlschlägt:

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

Weitere Informationen finden Sie unter: http://kotlinlang.org/docs/reference/null-safety.html

Sie können auch den "Null-Koaleszenz-Operator" verwenden (der für veränderbare Variablen funktioniert):

val b: Boolean? = null
if (b ?: false) {
    println(b)
}
Piotr Praszmo
quelle
Die Analyse funktioniert nur für unveränderliche Werte. Wenn Sie dies für ein veränderliches Feld tun müssen, speichern Sie es in einer temporären lokalen Variablen.
Piotr Praszmo
1
Das macht in der Tat Sinn. Der Null-Koaleszenz-Operator ist wahrscheinlich das, wonach ich gesucht habe. Vielen Dank!
Nhaarman
@Banthar, das nicht vollständig korrekt ist (Ihr zweites Beispiel wäre var?) ... Wenn es sich um ein lokales Beispiel handelt, kann varder Compiler die sichere Umwandlung weiterhin zulassen. Für weitere Sonderfälle lesen Sie stackoverflow.com/questions/34498562/…
Jayson Minard
Null Coalescing Elvis kann auf Zuordnung verschoben werdenval booleanVal = nullableProducer?.produceVal() ?: false; if (booleanVal) {}
Serge
6

Nach dem, was ich den Booleschen gesehen habe? ist das Ergebnis einer Methode, die Boolean für ein Objekt zurückgibt, das nullwertfähig ist

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

Die Lösung, die ich verwendet habe, besteht darin, die letFunktion zu verwenden, um den möglichen zurückgegebenen Nullwert wie folgt zu entfernen

person?.let {
  if(it.isHome()) {
    //Do something
  }
}
DroidT
quelle
5
Der erste wird kompiliert, wenn Sie den ifBlock durch ersetzen person?.isHome() == true.
Hesam
2

In Kotlin können Sie Folgendes tun:

val b: Boolean? = true
if (b == true) { // if b is null, this should be null == true
    /* Do something */
} else {
    /* Do something else */
}
ininmm
quelle
3
b != null && b == trueist das gleiche wie b == true.
Nhaarman
1

Fügen Sie zunächst die folgende benutzerdefinierte Inline-Funktion hinzu:

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
}

dann können Sie Code wie folgt schreiben:

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

//or

b.ifFalse {
   /* Do something else in false case */
}
zyc zyc
quelle
Ja, im Fall: b.ifTrue {...} oder b.ifFalse {...} kann es nützlich sein
zyc zyc
1

Für Kotlin benutze ich normalerweise

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

Dies würde nur funktionieren, wenn die Eigenschaft wahr ist und das Objekt nicht null ist. Für das Gegenteil:

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

Verwenden wir eine if-elseAnweisung mit 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!")
}

// Ergebnis: "Einer von ihnen ist nicht nullbar ..."

a = null
b = null

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

// Ergebnis: "Beide sind nullbar!"

Andy Fedoroff
quelle
0

Es ist ziemlich einfach, eine Erweiterungsfunktion hinzuzufügen, wenn dies hilfreich ist.

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

var x: Boolean? = null

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

Wenn Sie Operationen containan einem gleichermaßen ausführen möchten, können StringSie die Gleichheitsprüfung wie unten verwenden.

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

Sie können mit sicherem Operator "let" tun

val b: Boolean? = null
b?.let { flag ->
    if(flag){
        // true Block
    } else {
        // false Block
    }
}
Finalpets
quelle
Dies ist einfach nicht wahr und wird in einer Ausnahme zurückgegeben, die ausgelöst wird.
Nhaarman
Bearbeitet meine Antwort basierend auf dem vorherigen Kommentar
finalpets