返回值显然可以为null,但实际上不能

在Kotlin中做这个代码的习惯用法是什么?

private var someVar: SomeClass? = null private fun getSomeVar(): SomeClass { if (someVar == null) { someVar = getDefaultSomeVar() } return someVar } 

Android Studio会提醒我返回类型。 在Java中,这个代码是适当的和惯用的。 我的意思是,而不是改变返回类型为SomeClass? 也许还有更好的办法?

实际上, getSomeVar()永远不会返回null

编译器抱怨,因为理论上,不同的线程可能会改变赋值语句和返回语句之间的一些someVar

这里惯用的解决办法是使用财产代表团 :

 private val someVar: SomeClass by lazy { getDefaultSomeVar() } 

当它以线程安全的方式第一次被访问时,它初始化属性。 另外请注意,它现在是一个不可空的val,而不是一个可为空的var,这使得它通常更容易处理。

你确实失去了修改它的能力。 如果它需要变化,你现在必须自己做。 对于一个示例实现看到这个问题: Kotlin懒惰默认属性


以下两种解决方案将问题中的方法('java way')视为理所当然的,并且只是展示了一种防止编译器警告的方法。 然而,在你的情况下,这些都不建议,因为他们都有懒惰的初始化属性的缺点:

1)引入一个局部变量。 这个变量是安全的,不会被其他线程所改变,并且允许编译器做一个智能转换:

 private fun getSomeVar(): SomeClass { var value = someVar if(value == null) { value = getDefaultSomeVar() someVar = value } return value } 

该方法本身仍然不是线程安全的。 在多线程环境中,可以多次调用getDefaultSomeVar() ,并且不保证此方法的返回值等于someVar

2)使用!! :双爆运营商。 这将可空类型转换为不可空。 但是现在你失去了kotlin编译器对你执行的保护和无效的安全 。

 return someVar!! 

正如文件所说:“如果你想要一个NPE,你可以拥有它”

你可以写:

 return someVar!! 

这将返回一个非空值,但是如果它是空的,它会抛出一个NPE。

它可以更短,没有任何警告

  private fun getSomeVar(): SomeClass { return someVar?:getDefaultSomeVar() }