当前位置: 首页 > 知识库问答 >
问题:

Kotlin“Smart cast是不可能的,因为这个时候财产可能已经改变了”

郁高韵
2023-03-14

为什么Android Studio显示错误时,我使用2号脚本。我发现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
        }
    }
}

请解释一下这个案子

共有1个答案

弓俊晖
2023-03-14

IDE应该给您一个警告,说明在null检查之后,adapter.namelist有可能被另一个线程更改了,并且当您调用list.addAll(adapter.namelist)时,adapter.namelist实际上到那一点时可能为空(同样,因为另一个线程可能已经更改了该值。这将是一个竞争条件)。

您有几个解决方案:

>

  • 使namelist成为val,从而使其引用final。因为它是最终的,所以保证另一个线程不能更改它。这可能不适合您的用例。

    class Adapter {
        val nameList : ArrayList<String>? = null
    }
    

    在进行检查之前,创建一个本地的姓名列表副本。因为它是本地副本,编译器知道另一个线程不能访问它,因此不能更改它。在本例中,可以使用varval定义本地副本,但我建议使用val

    val nameList = adapter.nameList
    if (nameList != null) {
        list.addAll(nameList)
    }
    

    使用Kotlin提供的一个实用函数来处理这样的情况。let函数使用内联函数将其调用的引用复制为参数。这意味着它可以有效地编译成与#2相同的代码,但它更简洁一些。我更喜欢这个解决方案。

    adapter.nameList?.let { list.addAll(it) }
    

  •  类似资料: