Penggunaan Boolean? dalam ekspresi if

130

Jika saya memiliki nullable Boolean b, saya dapat melakukan perbandingan berikut di Java:

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

Di Kotlin, saya bisa mencapai hal yang sama dengan menggunakan !!operator:

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

Namun, penggunaan dari !!terasa agak samar bagi saya, menghindari sistem keamanan nol.

Apakah ada pendekatan yang lebih elegan untuk ini?


Sunting Sepertinya saya agak terlalu rumit. Untuk variabel lokal, seperti yang ditunjukkan Banthar , itu berhasil. Namun, Boolean saya bsebenarnya adalah "properti dengan bidang dukungan" (saya belum benar-benar memahami apa yang diberlakukan ini). Inilah hasilnya:

masukkan deskripsi gambar di sini

nhaarman
sumber
Mengapa Anda membutuhkan !!bdan tidak sekadar b? (Saya tidak begitu akrab dengan kotlin, hanya keingintahuan)
Maroun
1
@MarounMaroun Because bmay nulldan salah satu fitur Kotlin adalah Null Safety , yang memberikan kesalahan kompilasi saat mencoba mengevaluasi referensi nullable. Jadi, menggunakan polos bmemberikan kesalahan kompilasi :)
nhaarman
Tapi tidak akan b != nilmengerti sebelum memeriksa sisi kanan?
Maroun
Anda akan mengatakan memang, tapi IDE saya mengatakan sebaliknya. Saya ingat hal seperti itu seharusnya berhasil, saya akan melihat apakah saya dapat menemukan sesuatu.
nhaarman
Saya pikir val r = b?doSomething() ?: doSomethingElse()harus bekerja.
Maroun

Jawaban:

184

Anda dapat membandingkan boolean nullable dengan true, falseatau nullmenggunakan operator persamaan:

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
sumber
4
catatan: tampaknya tidak bekerja dengan operator terbalik!
Richard
7
@ Richard membantu untuk berpikir b sebagai memiliki 3 nilai yang mungkin: true, falseatau null. Kemudian ketika melakukan if (b != true)Anda hanya tahu bahwa b itu tidak benar, tetapi Anda tidak tahu apa-apa tentang falseataunull
jivimberg
7
eg2. if (b != true) // b is null or falseeg3. if (b == false) // b is false
hmac
Ini adalah jawaban yang benar dan masuk akal di Kotlin, tetapi berasal dari latar belakang Java, mungkin terasa aneh untuk membandingkan secara eksplisit dengan benar atau salah atau nol dalam pernyataan-if, yang mungkin menjelaskan mengapa ini pertanyaan dan jawaban yang populer.
Michael Peterson
31

Jika Anda ingin memeriksa dengan rapi apakah Boolean?adalah trueatau falseAnda dapat melakukan:

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

Jika Anda ingin memeriksa apakah nullAnda dapat menambahkannya (atau else) sebagai nilai di when:

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

when(b) {
    true -> {}
    false -> {}
    else-> {}
}
Eliezer
sumber
22

Kotlin akan menganalisis pemeriksaan null Anda secara statis. Ini bagus:

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

Meskipun ini gagal dengan kesalahan tipe:

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

Untuk lebih lanjut lihat: http://kotlinlang.org/docs/reference/null-safety.html

Anda juga dapat menggunakan "operator penggabungan nol" (yang akan berfungsi untuk variabel yang bisa berubah):

val b: Boolean? = null
if (b ?: false) {
    println(b)
}
Piotr Praszmo
sumber
Analisis hanya berfungsi untuk nilai yang tidak berubah. Jika Anda perlu melakukan ini ke kolom yang bisa diubah, simpan ke variabel lokal sementara.
Piotr Praszmo
1
Itu memang masuk akal. Operator penggabungan nol mungkin adalah yang saya cari. Terima kasih!
nhaarman
@Banthar itu tidak sepenuhnya benar (contoh kedua Anda adalah var?) ... jika itu lokal varmaka kompiler masih dapat mengizinkan cast yang aman. Untuk kasus yang lebih khusus, baca stackoverflow.com/questions/34498562/…
Jayson Minard
null coalescing elvis dapat dipindahkan ke tugasval booleanVal = nullableProducer?.produceVal() ?: false; if (booleanVal) {}
Serge
6

Dari apa yang saya lihat Boolean? adalah hasil dari metode yang mengembalikan Boolean pada objek yang nullable

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

Solusi yang saya gunakan adalah menggunakan letfungsi untuk menghapus kemungkinan nilai null yang dikembalikan seperti itu

person?.let {
  if(it.isHome()) {
    //Do something
  }
}
DroidT
sumber
5
Yang pertama dikompilasi jika Anda mengganti ifblok dengan person?.isHome() == true.
Hesam
2

Di Kotlin, Anda dapat melakukan seperti ini:

val b: Boolean? = true
if (b == true) { // if b is null, this should be null == true
    /* Do something */
} else {
    /* Do something else */
}
ininmm
sumber
3
b != null && b == truesama dengan b == true.
nhaarman
1

pertama, tambahkan fungsi sebaris kustom di bawah ini:

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
}

maka Anda dapat menulis kode seperti ini:

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

//or

b.ifFalse {
   /* Do something else in false case */
}
zyc zyc
sumber
Ya, dalam kasus: b.ifTrue {...} atau b.ifFalse {...} mungkin berguna
zyc zyc
1

Untuk Kotlin yang biasa saya gunakan adalah

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

ini hanya akan bekerja jika propertinya benar dan objeknya bukan null. Untuk kebalikannya:

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

Mari kita gunakan if-elsepernyataan dengan 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!")
}

// Hasil: "Salah satunya tidak dapat dibatalkan ..."

a = null
b = null

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

// Hasil: "Keduanya nullable!"

Andy Fedoroff
sumber
0

Sangat mudah untuk menambahkan fungsi ekstensi jika itu membantu Anda.

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

var x: Boolean? = null

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

Jika Anda ingin melakukan operasi serupa containdi sebuah StringAnda dapat menggunakan pemeriksaan kesetaraan seperti di bawah ini -

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

Anda dapat melakukannya dengan Operator yang aman "biarkan"

val b: Boolean? = null
b?.let { flag ->
    if(flag){
        // true Block
    } else {
        // false Block
    }
}
finalpets
sumber
Ini tidak benar, dan akan kembali dengan pengecualian yang dilemparkan.
nhaarman
Mengedit