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


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 
}

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-> {}
}

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)
}

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
  }
}

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 */
}

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 */
}

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
   }

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!”


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()) {
..
}

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;
}

-1

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

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

To po prostu nieprawda i zwróci w przypadku wyrzucenia wyjątku.
nhaarman

Zredagowałem moją odpowiedź na podstawie poprzedniego komentarza
finalpets
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.