Smart cast to 'Type' is impossible, because 'variable' is a mutable property that could have been changed by this time

匿名 (未验证) 提交于 2019-12-03 08:30:34

问题:

And the Kotlin newbie asks, "why won't the following code compile?":

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

Smart cast to 'Node' is impossible, because 'left' is a mutable property that could have been changed by this time

I get that left is mutable variable, but I'm explicitly checking left != null and left is of type Node so why can't it be smart-casted to that type?

How can I fix this elegantly? :)

回答1:

Between execution of n.left != null and queue.add(n.left) another thread could have changed the value of n.left to null.

To workaround this you have several options. Here are some:

  1. Use a local variable with smart cast:

    val left = n.left if (left != null) {     queue.add(left) } 
  2. Use a safe call such as one of the following:

    n.left?.let { left -> queue.add(left) } n.left?.let { queue.add(it) } n.left?.let(queue::add) 
  3. Use the Elvis operator with a jump to the next step of the enclosing while loop:

    queue.add(n.left ?: continue) 


回答2:

There is a fourth option in addition to the ones in mfulton26's answer.

By using the ?. operator it is possible to call methods as well as fields without dealing with let or using local variables.

Some code for context:

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

It works with methods, fields and all the other things I tried to get it to work.

So in order to solve the issue, instead of having to use manual casts or using local variables, you can use ?. to call the methods.

For reference, this was tested in Kotlin 1.1.4-3, but also tested in 1.1.51 and 1.1.60. There's no guarantee it works on other versions, it could be a new feature.

Using the ?. operator can't be used in your case since it's a passed variable that's the problem. The Elvis operator can be used as an alternative, and it's probably the one that requires the least amount of code. Instead of using continue though, return could also be used.

Using manual casting could also be an option, but this isn't null safe:

queue.add(left as Node); 

Meaning if left has changed on a different thread, the program will crash.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!