猿问

无法将类型强制转换为“类型”,因为“变量”是可变属性,到那时可能已经更改了

然后Kotlin新手问,“为什么下面的代码不编译?”:


    var left: Node? = null


    fun show() {

         if (left != null) {

             queue.add(left) // ERROR HERE

         }

    }

无法智能地将其强制转换为“节点”,因为“左”是一个可变属性,可能此时已更改


我得到的left是可变变量,但是我正在显式检查left != null并且left是类型,Node所以为什么不能将其智能转换为该类型?


我该如何解决?:)


LEATH
浏览 939回答 3
3回答

扬帆大鱼

在left != null和执行之间,queue.add(left)另一个线程可能将的值更改left为null。要解决此问题,您有几种选择。这里有一些:在智能转换中使用局部变量:val node = leftif (node != null) {    queue.add(node)}使用安全呼叫,例如以下之一:left?.let { node -> queue.add(node) }left?.let { queue.add(it) }left?.let(queue::add)使用Elvis运算符和return可以从封闭函数中提前返回:queue.add(left ?: return)请注意,break并且continue可以类似地用于循环内的检查。

小唯快跑啊

除了mfulton26的答案中的第四个选项。通过使用?.运算符,可以调用方法以及字段,而无需处理let或使用局部变量。一些上下文代码:var factory: ServerSocketFactory = SSLServerSocketFactory.getDefault();socket = factory.createServerSocket(port)socket.close()//smartcast impossiblesocket?.close()//Smartcast possible. And works when called它可以与方法,字段以及我尝试使其正常工作的所有其他事情一起使用。因此,为了解决此问题,您不必使用手动强制转换或使用局部变量,而可以使用?.来调用方法。作为参考,它在Kotlin中进行了测试1.1.4-3,但也在1.1.51和中进行了测试1.1.60。无法保证它可以在其他版本上使用,这可能是一项新功能。?.在您的情况下,不能使用运算符,因为这是传递的变量。Elvis运算符可以替代使用,它可能是需要最少代码量的运算符。除了使用之外continue,return还可以使用。也可以选择使用手动强制转换,但这不是null安全的方法:queue.add(left as Node);这意味着如果在其他线程上更改了left ,程序将崩溃。

一只斗牛犬

您也可以使用lateinitIf稍后在onCreate()其他地方进行初始化。用这个lateinit var left: Node代替这个var left: Node? = null还有这样使用!!变量结尾的其他方式queue.add(left!!) // add !!
随时随地看视频慕课网APP
我要回答