当我使用No.2脚本时,为什么Android Studio显示错误.我发现1和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
}
}
}
Run Code Online (Sandbox Code Playgroud)
请解释一下这个案子
spi*_*ce7 21
IDE应该给你一个警告,说明了空检查之后,它可能是adapter.nameList
被另一个线程改变,当你调用list.addAll(adapter.nameList)
,adapter.nameList
实际上可能是由点(再空,因为不同的线程可能已经改变了值.这将是竞争条件).
你有几个解决方案:
制作nameList
一个val
,作为参考final
.由于它是最终的,它保证了另一个线程无法改变它.这可能不适合您的用例.
class Adapter {
val nameList : ArrayList<String>? = null
}
Run Code Online (Sandbox Code Playgroud)在进行检查之前,请创建名称列表的本地副本.因为它是本地副本,所以编译器知道另一个线程无法访问它,因此无法更改它.本地副本可以使用a var
或者a 来定义val
,但我建议val
.
val nameList = adapter.nameList
if (nameList != null) {
list.addAll(nameList)
}
Run Code Online (Sandbox Code Playgroud)使用Kotlin提供的实用功能之一就是这样的情况.let函数使用内联函数将其调用的引用复制为参数.这意味着它有效地编译为与#2相同,但它更简洁一些.我更喜欢这个解决方案
adapter.nameList?.let { list.addAll(it) }
Run Code Online (Sandbox Code Playgroud)您的adapter.nameList是可变属性,因此请将其转换为不可变。
用这个
val nameList : ArrayList<String>? = null
Run Code Online (Sandbox Code Playgroud)
代替这个
var nameList : ArrayList<String>? = null
Run Code Online (Sandbox Code Playgroud)
或者您也可以通过断言非null断言来解决此问题
list.addAll(adapter.nameList!!)
Run Code Online (Sandbox Code Playgroud)
注意:- !! 在运行时评估,它只是一个运算符。
表达式(x !!)
如果x == null,则抛出KotlinNullPointerException,否则,将x强制转换为对应的不可为null的类型(例如,当调用类型为String?的变量时,它以String形式返回)。
归档时间: |
|
查看次数: |
18040 次 |
最近记录: |