作者:郑云雪 | 来源:互联网 | 2023-02-01 08:14
Kotlin新手问道,"为什么下面的代码不能编译?":
var left: Node? = null
fun show() {
if (left != null) {
queue.add(left) // ERROR HERE
}
}
智能转换为'Node'是不可能的,因为'left'是一个可变属性,此时可能已被更改
我得到的left
是可变变量,但是我明确地检查left != null
并且left
是类型的Node
,为什么它不能被智能化到那种类型?
我怎样才能优雅地解决这个问题?:)
1> mfulton26..:
在执行left != null
和queue.add(left)
另一个线程之间可能已经改变了left
to 的值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
可以类似地用于循环中的检查.
4.考虑一个不需要可变变量的问题的更实用的解决方案.
2> Zoe..:
除了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);
意思是如果在另一个线程上更改了左侧,程序将崩溃.
3> Radesh..:
您也可以使用lateinit
如果您稍后在onCreate()
其他地方进行初始化.
更改
lateinit var left: Node
至
var left: Node? = null