Why Android Studio show error when I use No.2 script. I found no different between 1 and 2.
class Adapter {
var nameList : ArrayList<String>? = null
}
class Program {
private fun send() {
val list: ArrayList<String> = ArrayList()
val adapter = Adapter()
// Case 1
var otherList = adapter.nameList
if (otherList != null) {
list.addAll(otherList) // <--- no error
}
// Case 2
if (adapter.nameList!=null) {
list.addAll(adapter.nameList) // <--- Error here
// Smart cast to 'kotlin.collections.ArrayList<String> /* = java.util.ArrayList<String> */' is impossible, because 'adapter.nameList' is a mutable property that could have been changed by this time
}
}
}
Please explain this case
The IDE should give you a warning, explaining that after the null check, it's possible that adapter.nameList
was changed by another thread, and that when you call list.addAll(adapter.nameList)
, adapter.nameList
could actually be null by that point (again, because a different thread could have changed the value. This would be a race condition).
You have a few solutions:
Make nameList
a val
, which makes its reference final
. Since it's final, it's guaranteed another thread can't change it. This probably doesn't fit your use case.
class Adapter {
val nameList : ArrayList<String>? = null
}
Create a local copy of name list before you do the check. Because it's a local copy, the compiler knows that another thread can't access it, and thus it can't be changed. The local copy could be defined with either a var
or a val
in this case, but I recommend val
.
val nameList = adapter.nameList
if (nameList != null) {
list.addAll(nameList)
}
Use one of the utility functions that Kotlin provides for just such a case as this. The let function copies the reference it's called on as a parameter using an inline function. This means that it effectively compiles down to be the same as #2, but it's a bit more terse. I prefer this solution.
adapter.nameList?.let { list.addAll(it) }
Your adapter.nameList is mutable property so please convert it to immutable.
Use this
val nameList : ArrayList<String>? = null
Instead of this
var nameList : ArrayList<String>? = null
Or you can also solve this problem by assert of non null Assert
list.addAll(adapter.nameList!!)
Note :- !! is evaluated at runtime, it's just an operator.
The expression (x!!)
throws a KotlinNullPointerException if x == null, otherwise, it returns x cast to the corresponding non-nullable type (for example, it returns it as a String when called on a variable with type String?).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With