Використання булевих? в, якщо вираз


130

Якщо у мене є нульовий Boolean b, я можу зробити таке порівняння на Java:

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

У Котліні я можу досягти цього за допомогою !!оператора:

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

Однак використання !!мені здається трохи схематичним, обходячи нульову систему безпеки.

Чи є для цього більш елегантний підхід?


Редагування Здається, я трохи спростив. Для локальних змінних, як показує Бантар , це працює. Однак мій булевий bнасправді є "властивістю із полем резервного" (я не дуже швидкий, але все, що це нав'язує). Це результат:

введіть тут опис зображення


Навіщо це потрібно, !!bа не просто b? (Я не такий знайомий з котліном, просто
цікаво

1
@MarounMaroun Оскільки, bможливо, nullоднією з особливостей Котліна є Null Safety , яка дає помилки компіляції при спробі оцінки нульових посилань. Таким чином, за допомогою звичайної bпомилки компіляції :)
nhaarman

Але не вдасться це b != nilзрозуміти, перш ніж перевірити праву сторону?
Maroun

Ви б сказали справді, але мій IDE говорить інакше. Я пам’ятаю, що щось подібне повинно працювати, я побачу, чи зможу щось знайти.
nhaarman

Я думаю, що val r = b?doSomething() ?: doSomethingElse()має працювати.
Maroun

Відповіді:


183

Ви можете порівняти обнуляє логічний з true, falseабо з nullдопомогою оператора рівності:

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
Примітка: схоже, не працює з оператором зворотного зв'язку!
Річард

7
@Richard це допомагає думати б як такі, що 3 можливих значень: true, falseабо null. Тоді при виконанні if (b != true)ви знаєте тільки , що б не так, але ви нічого не знаєте про falseабоnull
jivimberg

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

Це правильна відповідь і має сенс у Котліні, але, виходячи з фону Java, може бути дивно порівнювати з істинним чи хибним чи нульовим в операторі if, що може пояснити, чому це такий популярний питання та відповідь.
Майкл Петерсон

31

Якщо ви хочете чітко перевірити, чи Boolean?є, trueчи falseви можете це зробити:

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

Якщо ви хочете перевірити, чи це nullви, можете додати це (або else) як значення в поле when:

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

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

22

Котлін статистично проаналізує ваші нульові чеки. Це добре:

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

Незважаючи на те, що це не вдається з помилкою типу:

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

Докладніше див: http://kotlinlang.org/docs/reference/null-safety.html

Ви також можете скористатись "null coalescing operator" (який буде працювати для змінних змінних):

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

Аналіз працює лише на незмінні значення. Якщо вам потрібно зробити це до змінного поля, збережіть його у тимчасовій локальній змінній.
Piotr Praszmo

1
Це справді має сенс. Очевидно, що я шукав оператора зведення нуля. Дякую!
nhaarman

@Banthar, що не зовсім коректно (ваш другий приклад був би var?) ... якщо це локальний, varтоді компілятор все ще може дозволити безпечний склад. Більш детальні випадки читайте на сайті stackoverflow.com/questions/34498562/…
Jayson Minard

нульовий злиття ельвіса може бути переміщено до завданняval booleanVal = nullableProducer?.produceVal() ?: false; if (booleanVal) {}
Серж,

6

З того, що я бачив булевий? є результатом методу, який повертає булевий об'єкт, який є нульовим

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

Я використовую рішення - використовувати letфункцію для видалення можливого поверненого нульового значення, як-от так

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

5
Перший складається, якщо ви заміните ifблок на person?.isHome() == true.
Гесам

2

У Котліні ви можете зробити так:

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 == trueте саме, що b == true.
nhaarman

1

спочатку додайте спеціальну вбудовану функцію нижче:

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
}

тоді ви можете написати код так:

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

//or

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

Так, у випадку: b.ifTrue {...} або b.ifFalse {...} це може бути корисно
zyc zyc

1

Для Котліна те, що я зазвичай використовую

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

це буде працювати лише тоді, коли властивість вірна і об'єкт недійсний. Для зворотного:

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

0

Давайте використаємо if-elseоператор із 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!")
}

// Результат: "Один з них не зводиться до нуля ..."

a = null
b = null

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

// Результат: "Обидва є нульовими!"


0

Додавати функцію розширення можна досить просто, якщо це допоможе вам.

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

var x: Boolean? = null

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

0

Якщо ви хочете виконувати операції так само containна a, Stringви можете скористатися прапором рівності, як показано нижче -

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

-1

Ви можете зробити безпечний оператор "нехай"

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

Це просто не відповідає дійсності, і виняток буде викинутий.
nhaarman

Мою відповідь відредагував на основі попереднього коментаря
finalpets
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.