在Kotlin中进行编码的惯用方法是什么?
private var someVar: SomeClass? = null
private fun getSomeVar(): SomeClass {
if (someVar == null) {
someVar = getDefaultSomeVar()
}
return someVar
}
Android Studio警告我返回类型。但是,在Java中,这段代码是正确的,也是惯用的。我的意思是,不是将返回类型更改为SomeClass?
,而是还有更好的方法吗?
实际上,getSomeVar()
永远不会返回null
答案 0 :(得分:5)
编译器抱怨,因为理论上,不同的线程可以在赋值和return语句之间更改someVar
。
这里的惯用解决方案是使用property delegation:
private val someVar: SomeClass by lazy { getDefaultSomeVar() }
首次以线程安全方式访问属性时初始化该属性。另请注意,它现在是一个不可为空的val,而不是可空的var,这使得它通常更容易使用。
您确实无法在以后修改它。如果它需要是可变的,你现在必须自己做。有关示例实现,请参阅此SO问题:Kotlin lazy default property
以下两个解决方案将问题中的方法(“java方式”)视为理所当然,并且只显示防止编译器警告的方法。但是,在您的情况下,这些不建议,因为它们都比延迟初始化属性有缺点:
1)引入局部变量。这个变量不会被其他线程变异,并允许编译器进行Smart Cast:
private fun getSomeVar(): SomeClass {
var value = someVar
if(value == null) {
value = getDefaultSomeVar()
someVar = value
}
return value
}
然而,该方法本身仍然不是线程安全的。在多线程环境中,可以多次调用getDefaultSomeVar()
,并且无法保证此方法的返回值等于someVar
。
2)使用!!
:双重操作员。这会将可空类型转换为非可空类型。但现在你失去了kotlin编译器强制执行的保护和null safety。
return someVar!!
正如文档所说:'如果你想要一个NPE,你可以拥有它'
答案 1 :(得分:0)
你可以写:
return someVar!!
这将返回一个非空值,但如果它为null,则会抛出一个NPE。
答案 2 :(得分:0)
它可能更短,没有任何警告
private fun getSomeVar(): SomeClass {
return someVar?:getDefaultSomeVar()
}