Kotlin"聪明的演员阵容是不可能的,因为此时房产可能已被改变"

qua*_*kid 16 android kotlin

当我使用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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请解释一下这个案子

spi*_*ce7 21

IDE应该给你一个警告,说明了空检查之后,它可能是adapter.nameList被另一个线程改变,当你调用list.addAll(adapter.nameList),adapter.nameList实际上可能是由点(再空,因为不同的线程可能已经改变了值.这将是竞争条件).

你有几个解决方案:

  1. 制作nameList一个val,作为参考final.由于它是最终的,它保证了另一个线程无法改变它.这可能不适合您的用例.

    class Adapter {
        val nameList : ArrayList<String>? = null
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在进行检查之前,请创建名称列表的本地副本.因为它是本地副本,所以编译器知道另一个线程无法访问它,因此无法更改它.本地副本可以使用a var或者a 来定义val,但我建议val.

    val nameList = adapter.nameList
    if (nameList != null) {
        list.addAll(nameList)
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用Kotlin提供的实用功能之一就是这样的情况.let函数使用内联函数将其调用的引用复制为参数.这意味着它有效地编译为与#2相同,但它更简洁一些.我更喜欢这个解决方案

    adapter.nameList?.let { list.addAll(it) }
    
    Run Code Online (Sandbox Code Playgroud)


vis*_*gid 5

您的adapter.nameList是可变属性,因此请将其转换为不可变。

用这个

  val nameList : ArrayList<String>? = null
Run Code Online (Sandbox Code Playgroud)

代替这个

  var nameList : ArrayList<String>? = null
Run Code Online (Sandbox Code Playgroud)

或者您也可以通过断言非null断言来解决此问题

            list.addAll(adapter.nameList!!)
Run Code Online (Sandbox Code Playgroud)

注意:- !! 在运行时评估,它只是一个运算符。

表达式(x !!)

如果x == null,则抛出KotlinNullPointerException,否则,将x强制转换为对应的不可为null的类型(例如,当调用类型为String?的变量时,它以String形式返回)。

  • 这是不好的做法。使用`!!`确实表明您做错了事。应该使用`!!`非常罕见。 (2认同)