聪明的演员是不可能的,因为...是一个可变的属性,可以在这个时候改变

时间:2018-01-28 19:02:34

标签: 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
        }
    }

}

不幸的是它在比较中给了我错误

list !== null && list.size == 1

Smart cast to 'ReferenceArrayList<M>' is impossible, because 'list' is a mutable property that could have been changed by this time

据我所知,这与多线程假设有关。在Java中,如果期望多线程,我会创建函数synchronized。此外,如果我不编写线程安全的话,我可以完全忽略这一点。

我应该怎么写Kotlin?

我看到了这个解决方案https://stackoverflow.com/a/44596284/258483,但它预计MT,我不想这样做。如果做不到,如何避免智能铸造呢?

更新

问题是如何以相同的“程序”形式执行此操作。如何不使用智能铸造?

更新2

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

3 个答案:

答案 0 :(得分:2)

您可以执行空检查,如果成功,则使用let访问变量的只读副本:

fun isScalar() : Boolean {
    return list?.let { it.size == 1 } ?: false
}
  • 如果list为空,则整个let表达式将评估为null,并且将返回Elvis运算符(false)的右侧。
  • 如果list不为null,则调用let函数,并返回it.size == 1表达式的结果 - it引用{{1}的对象调用(在这种情况下为let)。由于它与safe call一起使用,因此list将具有非可空类型,并且可以在其上调用it

答案 1 :(得分:2)

如果你利用null不能等于1(或其他任何东西,真的)的事实,你可以非常简洁地进行检查:

fun isScalar() : Boolean =
    list?.size == 1

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

通过使用null安全操作符(?.),您完全避免使用智能转换。 Kotlin为我们提供了智能模型以使代码更清晰,这是它保护我们免受滥用功能的方法之一。 Kotlin不会保护我们免受任何事情的影响(例如,除以零,你在评论中使用的例子)。你的代码陷入了一个合理的情况,智能铸造可能出错,所以Kotlin跳槽帮忙。

但是,如果你完全确定没有其他线程可以工作,那么是的,这个检查是“错误的”。在这种情况下你不需要警告。从this thread on kotlinlang.org来看,你不是唯一的一个!

答案 2 :(得分:2)

在给定的行中我遇到了同样的问题

 sliderView.setSliderAdapter(adapter!!)
 sliderView.setIndicatorAnimation(IndicatorAnimationType.WORM)

最后,通过添加!!解决了错误

 sliderView!!.setSliderAdapter(adapter!!)
 sliderView!!.setIndicatorAnimation(IndicatorAnimationType.WORM)