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

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

智能转换为'Node'是不可能的,因为'left'是可变的 此时可以更改的属性

我得到left is mutable变量,但我显式检查left != null left是Node类型,为什么它不能被智能转换为这种类型?

我该如何优雅地解决这个问题?


当前回答

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

要解决这个问题,您有几个选择。以下是一些例子:

使用智能强制转换的局部变量: Val节点= left If (node != null) { queue.add(节点) } 使用一个安全的调用,例如以下之一: 离开吗?。让{node -> queue.add(node)} 离开吗?。Let {queue.add(it)} 离开?报价吧(队列::添加) 使用带有return的Elvis操作符提前从封闭函数返回: 队列中。Add (left ?: return) 注意,break和continue可以类似地用于循环中的检查。

其他回答

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

要解决这个问题,您有几个选择。以下是一些例子:

使用智能强制转换的局部变量: Val节点= left If (node != null) { queue.add(节点) } 使用一个安全的调用,例如以下之一: 离开吗?。让{node -> queue.add(node)} 离开吗?。Let {queue.add(it)} 离开?报价吧(队列::添加) 使用带有return的Elvis操作符提前从封闭函数返回: 队列中。Add (left ?: return) 注意,break和continue可以类似地用于循环中的检查。

除了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。

使用手动强制转换也可以是一个选择,但这不是空安全的:

queue.add(left as Node);

这意味着如果left在不同的线程上发生了改变,程序将崩溃。

1)你也可以使用lateinit如果你确定你将在onCreate()或其他地方进行初始化。

使用这个

lateinit var left: Node

而不是这个

var left: Node? = null

2)还有其他使用方法!!当你像这样使用它时,变量就结束了

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

这种方法不起作用的实际原因与线程无关。这个点就是那个节点。left被有效地转换为node.getLeft()。

这个属性getter可以定义为:

val left get() = if (Math.random() < 0.5) null else leftPtr

因此,两个调用可能不会返回相同的结果。

这样做:

var left: Node? = null

fun show() {
     val left = left
     if (left != null) {
         queue.add(left) // safe cast succeeds
     }
}

这似乎是公认答案提供的第一个选项,但这正是您要寻找的。