为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

LEATH 2019-10-16 13:58:20
然后Kotlin新手问,“为什么下面的代码不编译?”:    var left: Node? = null    fun show() {         if (left != null) {             queue.add(left) // ERROR HERE         }    }无法智能地将其强制转换为“节点”,因为“左”是一个可变属性,可能此时已更改我得到的left是可变变量,但是我正在显式检查left != null并且left是类型,Node所以为什么不能将其智能转换为该类型?我该如何解决?:)
查看完整描述

3 回答

?
扬帆大鱼

TA贡献1799条经验 获得超9个赞

在left != null和执行之间,queue.add(left)另一个线程可能将的值更改left为null。


要解决此问题,您有几种选择。这里有一些:


在智能转换中使用局部变量:


val node = left

if (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可以类似地用于循环内的检查。


查看完整回答
反对 回复 2019-10-16
?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

除了mfulton26的答案中的第四个选项。


通过使用?.运算符,可以调用方法以及字段,而无需处理let或使用局部变量。


一些上下文代码:


var factory: ServerSocketFactory = SSLServerSocketFactory.getDefault();

socket = factory.createServerSocket(port)

socket.close()//smartcast impossible

socket?.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 ,程序将崩溃。


查看完整回答
反对 回复 2019-10-16
?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

您也可以使用lateinitIf稍后在onCreate()其他地方进行初始化。


用这个


lateinit var left: Node

代替这个


var left: Node? = null

还有这样使用!!变量结尾的其他方式


queue.add(left!!) // add !!


查看完整回答
反对 回复 2019-10-16
  • 3 回答
  • 0 关注
  • 938 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信