智能转换是不可能的,因为 ... 是一个可变的属性,此时可能已经改变

Dim*_*ims 4 multithreading casting kotlin

我正在尝试获取一个类,它将列表、集合和映射结合到Kotlin. 我想写一个isScalar函数,true如果对象只包含一个元素,它应该返回并写

import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap
import it.unimi.dsi.fastutil.objects.ReferenceArrayList
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet

class Args {

    var list : ReferenceArrayList<M>? = null

    var set : ReferenceOpenHashSet<M>? = null

    var map : Reference2ReferenceOpenHashMap<M, M>? = null

    fun isEmpty() : Boolean {
        return list === null && set === null && map === null
    }

    fun isScalar() : Boolean {
        if(list !== null && list.size == 1) {
            return true
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

不幸的是,相比之下它给了我错误

list !== null && list.size == 1
Run Code Online (Sandbox Code Playgroud)

Smart cast to 'ReferenceArrayList<M>' is impossible, because 'list' is a mutable property that could have been changed by this time
Run Code Online (Sandbox Code Playgroud)

据我了解,这与多线程假设有关。在 Java 中,synchronized如果需要多线程,我会制作函数。另外,如果我不是在编写线程安全的,我完全可以忽略这一点。

我应该如何用 Kotlin 编写?

我看到了这个解决方案/sf/answers/3121739911/但它需要 MT,我不想。如果它不能做到,如何避免智能铸造?

更新

问题是如何以相同的“程序”形式做到这一点。如何不使用智能铸造?

更新 2

总结一下,据我所知,null在 Kotlin 中明确比较变量是不可能/不合理的。因为一旦你比较了它,下次你应该用null类似这样的操作隐式地再次比较它,.?你无法避免这种情况。

Tod*_*odd 6

如果您利用null不等于1(或其他任何东西,真的)这一事实,您可以使此检查非常简洁:

fun isScalar() : Boolean =
    list?.size == 1
Run Code Online (Sandbox Code Playgroud)

当对空值安全的调用list.size返回空值时,我们得到false因为1 != null。否则,size会对返回的任何值进行比较,这将按您的预期工作。

通过使用空安全运算符 ( ?.),您可以完全避免智能转换。Kotlin 为我们提供了智能强制转换以使代码更简洁,这是它保护我们免受滥用该功能的方法之一。Kotlin 不会保护我们免受一切影响(例如被零除,您在评论中使用的示例)。您的代码遇到了智能转换可能出错的合理情况,因此 Kotlin 会提供帮助。

但是,如果您绝对确定没有其他线程在工作,那么是的,此检查是“错误的”。在这种情况下,您不需要警告。从kotlinlang.org 上这个帖子来看,你不是唯一一个!