智能转换为“types”是不可能的,因为“variables”是一个可以改变的可变属性

Kotlin新手问道: “为什么下面的代码不能编译?”

var left: Node? = null fun show() { if (left != null) { queue.add(left) // ERROR HERE } } 

智能投到“节点”是不可能的,因为“左”是一个可变的属性,可能已经改变了这个时间

我得到left是可变的variables,但我显式检查left != nullleftNodetypes,为什么不能聪明地转换为该types?

我怎样才能解决这个优雅? 🙂

在执行n.left != nullqueue.add(n.left)另一个线程可能n.left的值n.leftnull

要解决这个问题,你有几个选择。 这里有一些:

  1. 使用智能转换使用本地variables:

     val left = n.left if (left != null) { queue.add(left) } 
  2. 请使用以下安全呼叫之一:

     n.left?.let { left -> queue.add(left) } n.left?.let { queue.add(it) } n.left?.let(queue::add) 
  3. 使用Elvis操作符 跳转到封闭while循环的下一步:

     queue.add(n.left ?: continue) 

除了mfulton26的答案之外,还有第四种选择。

通过使用?. 运算符可以调用方法以及字段而不用处理let或使用局部variables。

上下文的一些代码:

 var factory: ServerSocketFactory = SSLServerSocketFactory.getDefault(); socket = factory.createServerSocket(port) socket.close()//smartcast impossible socket?.close()//Smartcast possible. And works when called 

它与方法,领域和所有其他的东西,我试图让它的工作。

所以为了解决这个问题,不必使用手动转换或使用局部variables,你可以使用?. 调用方法。

作为参考,这在Kotlin 1.1.4-3中进行了测试,但也在1.1.511.1.60进行了测试。 不能保证它可以在其他版本上运行,这可能是一个新function。

使用?. 运算符不能用于你的情况,因为它是一个通过variables,这是问题。 Elvis算子可以作为一个替代方案,也可能是最少量的代码。 不用continue使用,也可以使用return

使用手动铸造也可以是一个选项,但这不是零安全的:

 queue.add(left as Node); 

意思是如果在不同的线程上左改变了,程序将会崩溃。