当我尝试创建以下代码时:
class SmartCast {
var array: MutableList<Int>? = null
fun processArray() {
if (array != null && !array.isEmpty()) {
// process
}
}
}
Run Code Online (Sandbox Code Playgroud)
显示此错误:
无法智能地强制将其强制转换为“ MutableList”,因为“数组”是一个可变属性,到那时可能已经更改了
显然,在多线程的情况下,array可以将变量更改为null。但是,如果使用@Synchronized批注,则无法在array != null和之间对变量进行突变!array.isEmpty()。
@Synchronized
fun processArray() {
Run Code Online (Sandbox Code Playgroud)
我想知道为什么编译器不允许在同步块中进行智能转换,或者也许可以指定我的应用程序仅设计用于单线程模式?
更新:根据答案,我以以下方式更改了代码:
fun processArray() {
array?.takeUnless { it.isEmpty() }?.also {
for (elem in it)
// process elements
}
}
Run Code Online (Sandbox Code Playgroud)
将列表保存到本地变量,然后使用该本地变量。做到这一点的一种优雅方法是使用该let函数,并将其与null安全运算符组合:
array?.let {
if (!it.isEmpty()) {
// process it
}
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器不允许在同步块中进行智能转换
因为这
但是如果我使用@Synchronized 注释,则无法在数组 != null 和 !array.isEmpty() 之间改变变量。
是错的。@Synchronized意味着这个方法不能同时被两个线程调用,但是另一个可以访问同一个实例的线程完全可以自由地重新分配array。
您还需要将 setter 标记为@Synchronized,在这种情况下,目前确实无法更改。但是试图弄清楚智能转换什么时候是安全的会导致非常复杂的规则,一种方法的微小变化会突然破坏其他方法的智能转换。所以规则是保守的。
| 归档时间: |
|
| 查看次数: |
510 次 |
| 最近记录: |