Użycie wartości logicznej? w wyrażeniu if

131

Jeśli mam wartość null Boolean b, mogę wykonać następujące porównanie w Javie:

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

W Kotlinie to samo mogę osiągnąć za pomocą !!operatora:

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

Jednak użycie !!jest dla mnie trochę szkicowe, omijając zerowy system bezpieczeństwa.

Czy jest na to bardziej eleganckie podejście?


Edycja Wygląda na to, że trochę przesadziłem. W przypadku zmiennych lokalnych, jak pokazuje Banthar , działa. Jednak moja wartość logiczna bjest w rzeczywistości „właściwością z polem zapasowym” (nie jestem jeszcze na bieżąco z tym, co to narzuca). Oto wynik:

wprowadź opis obrazu tutaj

nhaarman
źródło
Dlaczego potrzebujesz, !!ba nie po prostu b? (Nie jestem zbyt zaznajomiony z kotlinem, tylko ciekawostki)
Maroun
1
@MarounMaroun Odkąd bmoże być, nulla jedną z funkcji Kotlina jest Null Safety , która daje błędy kompilacji podczas próby oceny referencji dopuszczających wartość null. Tak więc użycie zwykłego bdaje błąd kompilacji :)
nhaarman
Ale czy nie b != nilzłapiesz tego przed sprawdzeniem prawej strony?
Maroun
Powiedziałbyś, że rzeczywiście, ale moje IDE mówi inaczej. Pamiętam, że coś takiego powinno działać, zobaczę, czy coś znajdę.
nhaarman
Myślę, że val r = b?doSomething() ?: doSomethingElse()powinno działać.
Maroun

Odpowiedzi:

185

Można porównać zerowalne logiczną z true, falselub nullza pomocą operatora równości:

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
źródło
4
uwaga: wydaje się, że nie działa z operatorem odwrotnym!
Richard
7
@Richard pomaga myśleć B jako mający 3 możliwych wartości: true, falselub null. Wtedy, robiąc if (b != true), wiesz tylko, że b nie jest prawdą, ale nic nie wiesz o falselubnull
jivimberg
7
eg2. if (b != true) // b is null or falseeg3. if (b == false) // b is false
hmac
To jest poprawna odpowiedź i ma sens w Kotlinie, ale na tle Java może wydawać się dziwne, aby jawnie porównać z prawdą, fałszem lub null w instrukcji if, co może wyjaśniać, dlaczego jest to tak popularne pytanie i odpowiedź.
Michael Peterson
32

Jeśli chcesz dokładnie sprawdzić, czy Boolean?jest truelub falsemożesz:

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

Jeśli chcesz sprawdzić, czy tak jest null, możesz dodać to (lub else) jako wartość w when:

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

when(b) {
    true -> {}
    false -> {}
    else-> {}
}
Eliezer
źródło
22

Kotlin będzie analizować statycznie twoje czeki zerowe. Jest okej:

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

Mimo że to się nie powiedzie z błędem typu:

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

Więcej na: http://kotlinlang.org/docs/reference/null-safety.html

Możesz także użyć „operatora łączenia wartości null” (który będzie działał dla zmiennych zmiennych):

val b: Boolean? = null
if (b ?: false) {
    println(b)
}
Piotr Praszmo
źródło
Analiza działa tylko dla niezmiennych wartości. Jeśli chcesz to zrobić w zmiennym polu, zapisz je w tymczasowej zmiennej lokalnej.
Piotr Praszmo
1
To rzeczywiście ma sens. Operator koalescencji zerowej jest prawdopodobnie tym, czego szukałem. Dzięki!
nhaarman
@Banthar, który nie jest całkowicie poprawny (Twój drugi przykład to var?) ... jeśli jest to plik lokalny, varkompilator nadal może zezwolić na bezpieczne rzutowanie. Więcej informacji na temat specjalnych przypadków można znaleźć na stronie stackoverflow.com/questions/34498562/ ...
Jayson Minard
null łączący się elvis może zostać przeniesiony do przydziałuval booleanVal = nullableProducer?.produceVal() ?: false; if (booleanVal) {}
Serge,
7

Z tego co widziałem Boolean? jest wynikiem metody, która zwraca wartość logiczną dla obiektu, który ma wartość null

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

Rozwiązaniem, którego używałem, jest użycie letfunkcji do usunięcia możliwej zwróconej wartości null w ten sposób

person?.let {
  if(it.isHome()) {
    //Do something
  }
}
DroidT
źródło
5
Pierwsza kompiluje się, jeśli zastąpisz ifblok przez person?.isHome() == true.
Hesam
2

W Kotlinie możesz zrobić tak:

val b: Boolean? = true
if (b == true) { // if b is null, this should be null == true
    /* Do something */
} else {
    /* Do something else */
}
inmm
źródło
3
b != null && b == truejest taki sam jak b == true.
nhaarman
1

najpierw dodaj niestandardową funkcję wbudowaną poniżej:

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
}

możesz napisać taki kod:

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

//or

b.ifFalse {
   /* Do something else in false case */
}
zyc zyc
źródło
Tak, w przypadku: b.ifTrue {...} lub b.ifFalse {...} może się przydać
zyc zyc
1

Dla Kotlina zwykle używam

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

działałoby to tylko wtedy, gdy właściwość ma wartość true, a obiekt nie jest pusty. Na odwrót:

if (!object?booleanProperty !=true)
   { 
     //do Stuff
   }
Jan
źródło
0

Użyjmy if-elseinstrukcji z 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!")
}

// Wynik: „Jeden z nich nie dopuszcza wartości null ...”

a = null
b = null

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

// Wynik: „Oba są wartościami zerowymi!”

Andy Fedoroff
źródło
0

Dodanie funkcji rozszerzenia jest dość łatwe, jeśli ci to pomoże.

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

var x: Boolean? = null

if(x.orDefault()) {
..
}
Nic Bell
źródło
0

W przypadku, gdy chcesz wykonać podobne operacje containna a, Stringmożesz użyć sprawdzenia równości, jak poniżej -

if (url?.contains("xxx") == true){
  return false;
}
Anoop M.
źródło
-1

Możesz to zrobić z bezpiecznym operatorem „pozwól”

val b: Boolean? = null
b?.let { flag ->
    if(flag){
        // true Block
    } else {
        // false Block
    }
}
Finalpets
źródło
To po prostu nieprawda i zwróci w przypadku wyrzucenia wyjątku.
nhaarman
Zredagowałem moją odpowiedź na podstawie poprzedniego komentarza
finalpets