Which one should I use between if (data!=null) and

2019-05-28 02:29发布

问题:

The Code A is common usage in java.

I havn't understanded completely the key let of Kotin. Which one should I use between Code A and Code B in kotlin? Thanks!

Code A

if (data!=null){
    initAndBindAdapter()
    mCustomAdapter.setSelectedIndex(data.getIntExtra("index",-1))
}    

Code B

 data?.let {
    initAndBindAdapter()
    mCustomAdapter.setSelectedIndex(it.getIntExtra("index",-1))
 }

And more, which one should I choose between Code C and Code D in kotlin if the fun do_NoNeed_data_par doesn't need data parameter ?

Code C

   if (data!=null){
        do_NoNeed_data_par()        
    }

Code D

   data?.let {
       do_NoNeed_data_par()    
    }

回答1:

I (personal opinion) think it's a good idea to use simple, regular null checks where you can, although the ?.let method has been listed under the main Kotlin Idioms page of the documentation (which is open for the community to contribute) - so basically, this will be up to your personal preferences of which one is more readable.

The more interesting question is what are the differences, and when you can use each: the main difference is that let holds on to the value of the variable as it was when the let call on it started, and any subsequent uses of it within the let block will reference that same value. If you use a simple null check with if, your variable's value might be changed while the body of the if block is being executed.

So for example, this won't compile, because x can be accessed by multiple threads, and it might be non-null when you read its value first for the null check, but it might become null by the time you read it again for the println parameter - this would be unsafe:

class Foo {
    var x: Int? = null

    fun useX() {
        if (x != null) {
            println(x + 10) // (...) 'x' is a mutable property that could have been changed by this time
        }
    }
}

However, a let will work in the same situation, because it will use whatever the initial value of x had all throughout its execution, even if the x property in the class gets reassigned in the meantime:

class Foo {
    var x: Int? = null

    fun useX() {
        x?.let {
            println(it + 10)
        }
    }
}

You can think of the ?.let statement above of basically performing this, creating a temporary copy of your variable:

fun useX() {
    val _x = x
    if (_x != null) {
        println(_x + 10)
    }
}

Operating on this copy is safe, because even if the x property changes its value, this _x copy will either stay null for this entire function, or it's non-null and safe to use.



回答2:

"should" is opinionated. It all depends on your preference.

If you prefer more functional style code then .let is your answer. If you prefer more procedural code then == null is your answer.



回答3:

Sometimes, using let() can be a concise alternative for if. But you have to use it with sound judgment in order to avoid unreadable “train wrecks”. Nevertheless, I really want you to consider using let().

val order: Order? = findOrder()
if (order != null){
dun(order.customer)
}

With let(), there is no need for an extra variable. So we get along with one expression.

findOrder()?.let { dun(it.customer) }