Sử dụng Boolean? trong biểu thức if


130

Nếu tôi có giá trị nullable Boolean b, tôi có thể thực hiện phép so sánh sau trong Java:

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

Trong Kotlin, tôi có thể đạt được điều tương tự bằng cách sử dụng !!toán tử:

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

Tuy nhiên, với tôi, việc sử dụng !!cảm giác hơi sơ sài, phá vỡ hệ thống an toàn vô hiệu.

Có một cách tiếp cận thanh lịch hơn cho điều này?


Chỉnh sửa Có vẻ như tôi đã đơn giản hóa một chút. Đối với các biến cục bộ, như Banthar cho thấy, nó hoạt động. Tuy nhiên, Boolean của tôi bthực sự là một "thuộc tính có trường hỗ trợ" (tôi thực sự chưa bắt kịp tốc độ mà điều này áp đặt). Đây là kết quả:

nhập mô tả hình ảnh ở đây


Tại sao bạn cần !!bvà không đơn giản b? (Tôi không quen thuộc với kotlin, chỉ tò mò)
Maroun

1
@MarounMaroun Since bcó thể là nullvà một trong những tính năng của Kotlin là Null Safety , đưa ra lỗi biên dịch khi cố gắng đánh giá các tham chiếu có thể trống. Vì vậy, sử dụng đơn giản bđưa ra một lỗi biên dịch :)
nhaarman

Nhưng sẽ không b != nilnắm bắt được điều đó trước khi kiểm tra phía bên phải?
Maroun

Bạn sẽ nói thực sự, nhưng IDE của tôi nói khác. Tôi nhớ rằng một cái gì đó như vậy sẽ hoạt động, tôi sẽ xem nếu tôi có thể tìm thấy một cái gì đó.
nhaarman

Tôi nghĩ val r = b?doSomething() ?: doSomethingElse()nên làm việc.
Maroun

Câu trả lời:


184

Bạn có thể so sánh boolean nullable với true, falsehoặc nullsử dụng nhà điều hành bình đẳng:

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
lưu ý: dường như không hoạt động với toán tử nghịch đảo!
Richard

7
@ Richard nó giúp chúng ta nghĩ b là có 3 giá trị có thể: true, falsehoặc null. Sau đó, khi thực hiện if (b != true)bạn chỉ biết rằng b là không đúng sự thật, nhưng bạn không biết gì về falsehaynull
jivimberg

7
vd2. if (b != true) // b is null or falseví dụ: 3. if (b == false) // b is false
hmac

Đây là câu trả lời chính xác và có ý nghĩa trong Kotlin, nhưng đến từ nền tảng Java, có thể cảm thấy lạ khi so sánh rõ ràng với true hoặc false hoặc null trong câu lệnh if, điều này có thể giải thích tại sao đây là một câu hỏi và câu trả lời phổ biến như vậy.
Michael Peterson

31

Nếu bạn muốn kiểm tra rõ ràng xem có phải Boolean?truehoặc falsebạn có thể làm:

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

Nếu bạn muốn kiểm tra xem đó có phải là không, nullbạn có thể thêm (hoặc else) đó làm giá trị trong when:

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

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

22

Kotlin sẽ phân tích tĩnh các kiểm tra null của bạn. Điều này là tốt:

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

Mặc dù điều này không thành công với lỗi loại:

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

Để biết thêm chi tiết, hãy xem: http://kotlinlang.org/docs/reference/null-safety.html

Bạn cũng có thể sử dụng "toán tử liên kết null" (sẽ hoạt động với các biến có thể thay đổi):

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

Phân tích chỉ hoạt động đối với các giá trị bất biến. Nếu bạn cần thực hiện việc này với một trường có thể thay đổi, hãy lưu trữ nó vào biến cục bộ tạm thời.
Piotr Praszmo

1
Điều đó có ý nghĩa, thực sự. Toán tử liên kết null có lẽ là những gì tôi đang tìm kiếm. Cảm ơn!
nhaarman

@Banthar điều đó không hoàn toàn chính xác (ví dụ thứ hai của bạn sẽ là var?) ... nếu nó là cục bộ varthì trình biên dịch vẫn có thể cho phép truyền an toàn. Đối với các trường hợp đặc biệt hơn, hãy đọc stackoverflow.com/questions/34498562/…
Jayson Minard

null kết hợp elvis có thể được chuyển đến nhiệm vụval booleanVal = nullableProducer?.produceVal() ?: false; if (booleanVal) {}
Serge

6

Từ những gì tôi đã thấy Boolean? là kết quả của một phương thức trả về Boolean trên một đối tượng là nullable

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

Giải pháp tôi đang sử dụng là sử dụng lethàm để loại bỏ giá trị null có thể trả về như vậy

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

5
Cái đầu tiên biên dịch nếu bạn thay thế ifkhối bằng person?.isHome() == true.
Hesam

2

Trong Kotlin, bạn có thể làm như sau:

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 == truegiống như b == true.
nhaarman

1

trước tiên, hãy thêm hàm nội tuyến tùy chỉnh bên dưới:

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
}

thì bạn có thể viết mã như thế này:

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

//or

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

Vâng, trong trường hợp: b.ifTrue {...} hoặc b.ifFalse {...} nó có thể hữu ích
zyc zyc

1

Đối với Kotlin, những gì tôi thường sử dụng là

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

điều này sẽ chỉ hoạt động khi thuộc tính là true và đối tượng không phải là null. Ngược lại:

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

0

Hãy sử dụng một if-elsecâu lệnh với 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!")
}

// Kết quả: "Một trong số chúng không thể null ..."

a = null
b = null

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

// Kết quả: "Cả hai đều là nullable!"


0

Thật dễ dàng để thêm một chức năng mở rộng nếu điều đó giúp ích cho bạn.

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

var x: Boolean? = null

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

0

Trong trường hợp nếu bạn muốn thực hiện các hoạt động giống nhau containtrên một, Stringbạn có thể sử dụng kiểm tra bình đẳng như bên dưới:

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

-1

Bạn có thể làm với Toán tử an toàn "let"

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

Điều này đơn giản là không đúng, và sẽ trả về trong một trường hợp ngoại lệ được ném ra.
nhaarman

Thay đổi nội dung câu trả lời của tôi dựa trên những nhận xét trước đó
finalpets
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.