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()
}
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.
"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.
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) }