การใช้บูลีน? ในนิพจน์ if


130

หากฉันมีค่าว่างBoolean bฉันสามารถทำการเปรียบเทียบต่อไปนี้ใน Java:

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

ใน Kotlin ฉันสามารถบรรลุสิ่งเดียวกันได้โดยใช้ตัว!!ดำเนินการ:

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

อย่างไรก็ตามการใช้งานของฉัน!!รู้สึกเป็นร่างเล็กน้อยสำหรับฉันหลีกเลี่ยงระบบความปลอดภัยว่าง

มีแนวทางที่หรูหรากว่านี้หรือไม่?


แก้ไขดูเหมือนว่าฉันจะซับซ้อนไปหน่อย สำหรับตัวแปรท้องถิ่นดังที่Bantharแสดงให้เห็นว่ามันใช้งานได้ อย่างไรก็ตามบูลีนของฉันbเป็น "คุณสมบัติที่มีฟิลด์สำรอง" (ฉันยังไม่เร่งความเร็วเท่าไหร่) นี่คือผลลัพธ์:

ใส่คำอธิบายภาพที่นี่


ทำไมคุณถึงต้องการ!!bและไม่เพียงb? (ฉันไม่ค่อยคุ้นเคยกับ kotlin แค่อยากรู้อยากเห็น)
Maroun

1
@MarounMaroun เนื่องจากbอาจเป็นnullและหนึ่งในคุณสมบัติของ Kotlin คือNull Safetyซึ่งทำให้เกิดข้อผิดพลาดในการรวบรวมเมื่อพยายามประเมินการอ้างอิงที่เป็นโมฆะ ดังนั้นการใช้ธรรมดาbจะทำให้เกิดข้อผิดพลาดในการคอมไพล์ :)
nhaarman

แต่จะไม่b != nilจับก่อนที่จะตรวจสอบด้านขวา?
Maroun

คุณจะพูดว่าจริง แต่ IDE ของฉันพูดเป็นอย่างอื่น ฉันจำได้ว่าบางอย่างก็น่าจะใช้ได้ฉันจะดูว่าฉันจะหาอะไรได้ไหม
nhaarman

คิดว่าน่าval r = b?doSomething() ?: doSomethingElse()จะใช้ได้นะ
Maroun

คำตอบ:


184

คุณสามารถเปรียบเทียบบูลีนที่เป็นโมฆะ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
หมายเหตุ: ดูเหมือนจะไม่ทำงานกับตัวดำเนินการผกผัน!
Richard

7
@ ริชาร์ดช่วยให้คิดว่า b มี 3 ค่าที่เป็นไปได้: true, falseหรือnull. จากนั้นเมื่อif (b != true)คุณรู้เพียงว่า b ไม่จริง แต่คุณไม่รู้อะไรเลยfalseหรือnull
jivimberg

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

นี่เป็นคำตอบที่ถูกต้องและสมเหตุสมผลใน Kotlin แต่มาจากพื้นหลัง Java อาจรู้สึกแปลกที่จะเปรียบเทียบกับจริงหรือเท็จหรือโมฆะอย่างชัดเจนภายในคำสั่ง if ซึ่งอาจอธิบายได้ว่าเหตุใดจึงเป็นคำถามและคำตอบยอดนิยม
Michael Peterson

31

หากคุณต้องการตรวจสอบอย่างละเอียดว่า a Boolean?is trueหรือfalseคุณสามารถทำได้:

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

หากคุณต้องการตรวจสอบว่าnullคุณสามารถเพิ่ม (หรือelse) เป็นค่าในwhen:

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

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

22

Kotlin จะวิเคราะห์การตรวจสอบค่าว่างของคุณแบบคงที่ นี่เป็นเรื่องปกติ:

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ฟังก์ชันเพื่อลบค่า null ที่ส่งคืนที่เป็นไปได้เช่นนั้น

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

5
คนแรก compiles ถ้าคุณแทนที่บล็อกโดยif person?.isHome() == true
Hesam

2

ใน Kotlin คุณสามารถทำได้ดังนี้:

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

สำหรับ Kotlin สิ่งที่ฉันใช้ตามปกติคือ

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บน Stringคุณสามารถใช้ตรวจสอบความเท่าเทียมกันเช่นนี้ -

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

-1

คุณสามารถทำได้โดยปลอดภัย Operator "let"

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

สิ่งนี้ไม่เป็นความจริงและจะกลับมาในกรณีที่ถูกโยนทิ้ง
nhaarman

แก้ไขคำตอบของฉันตามความคิดเห็นก่อนหน้า
finalpets
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.