为什么当我使用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
}
}
}
请解释这个案例
< code>adapter.nameList是一个可能已被更改的可变属性
出现此检查和错误消息的原因是线程。您所拥有的称为竞争条件。在许多类似的情况下,另一个线程可能会在空值检查和list.addAll
调用之间更改adapter.namelist
的值。显然,这在您的情况下不会发生,因为适配器没有从发送函数中泄露,但我猜编译器不够聪明,无法知道这一点。
相反,在案例1中没有竞争条件,因为名称列表只被访问一次。
如果名称列表
是val
,而不是var
-这也不会发生,因为编译器知道它不能更改-因此它不能从非null更改为null。
您的 adapter.nameList 是可变属性,因此请将其转换为不可变属性。
使用这个
val nameList : ArrayList<String>? = null
代替此
var nameList : ArrayList<String>? = null
或者,您也可以通过断言非空 Assert 来解决此问题
list.addAll(adapter.nameList!!)
注意:-!!在运行时评估,它只是一个运算符。
表达式(x!)
如果 x == null,则抛出一个 KotlinNullPointerException,否则,它将 x 强制转换为相应的不可为 null 的类型(例如,当对 String? 类型的变量调用时,它会将其作为 String 返回)。
IDE会向您发出警告,说明在进行空值检查后,< code>adapter.nameList可能已被另一个线程更改,并且当您调用< code > list . addall(adapter . name list)时,< code>adapter.nameList实际上可能已为空值(同样,因为另一个线程可能已更改了该值)。这将是一种竞争条件)。
您有一些解决方案:
>
将 nameList
设置为 val
,这将使其引用成为最终值
。由于它是最终的,因此可以保证另一个线程无法更改它。这可能不适合您的使用案例。
class Adapter {
val nameList : ArrayList<String>? = null
}
在执行检查之前,请创建名称列表的本地副本。因为它是本地副本,所以编译器知道另一个线程无法访问它,因此无法更改它。在这种情况下,本地副本可以用 var
或 val
来定义,但我建议使用 val
。
val nameList = adapter.nameList
if (nameList != null) {
list.addAll(nameList)
}
使用Kotlin为这种情况提供的实用程序函数之一。let函数使用内联函数复制作为参数调用的引用。这意味着它可以有效地编译成与#2相同的格式,但要简洁一些。我更喜欢这个解决方案。
adapter.nameList?.let { list.addAll(it) }
我正在用kotlin为android制作一个小型tasker。我将主要活动分成一些片段,然后为每个片段创建一个视图模型。但是现在这里出现了一个问题。 下面是一些代码: 我本来希望在observer方法的帮助下在主屏幕上看到一些创建的单选按钮,但是我得到了一个例外,这在问题的标题中提到。提前感谢您的帮助!
智能转换为“GridLayoutManager”是不可能的,因为“ViewManager”是一个可变属性,此时可能已更改 是错误,AndroidStudio显示时,试图添加一个除法器到我的回收视图。 PixelsFragment.kt 我找到了这个答案,它说这样的问题可能是因为在执行该行时变量可能碰巧为< code>null,然后他们提供了3个解决方案。然而,根据我的理解,< code>viewM
我知道是可变变量,但我显式检查了并且是类型,那么为什么不能智能转换为该类型呢? 我怎样才能把它修好呢?
我尝试将我的代码从java转换为kotlin,因此我面临这个错误。我不明白为什么我会得到这个错误 错误 我只是附加给我一个错误的代码并突出显示它
我还在另一个类中使用了bitmap2和Bitmap1: 这里写着:类型不匹配,必需:位图找到:位图?
我正在尝试在 Kotlin 中生成一个单例,并且遇到了问题,因为我无法。 这似乎是制作单例的一种非常标准的方法。为什么它不让我,我该如何解决它?