2017-04-15 22 views
2

在Kotlin中执行代码的惯用方法是什么?一个变量的返回值,显然可以为null,但实际上不可能

private var someVar: SomeClass? = null 

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

     return someVar 
    } 

Android Studio警告我关于返回类型。然而,在Java中,这个代码是适当的和惯用的。我的意思是,而不是将返回类型更改为SomeClass?也许还有更好的方法?

其实,getSomeVar()永远不能返回null

+1

有什么警告?首选项在哪里? –

回答

0

你可以写:

return someVar!! 

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

5

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

这里的惯用解决方案是使用property delegation

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

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

您确实失去了稍后修改它的能力。如果它需要变化,你现在必须自己做。示例实现看到这个SO问题:Kotlin lazy default property


以下两种解决方案采取方法的问题(即“Java的方式”)是理所当然的,只是显示方式,以防止编译器警告。然而,在你的情况下,这些是而不是建议,因为他们都有懒惰初始化属性的缺点:

1)引入一个局部变量。这个变量是安全,不会被其他线程正在发生突变,并允许编译器做一个聪明的演员:

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

    return value 
} 

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

2)使用!!:double bang操作符。这将可空类型转换为不可空。但是现在你失去了kotlin编译器对你执行的保护和null safety

return someVar!! 

由于文档所说的那样:“如果你想要一个NPE,你可以把它”

+0

您的解决方案1不会阻止'someVar = value'和'return value'之间的'someVar'修改。所以'getSomeVar()'的调用者的返回值可能与变量的实际值不同。所以这应该真的被改为一个懒惰的初始化val,正如你所建议的那样。 –

+0

@PJMeisch你是对的,谢谢。我编辑了答案也反映了这一点。 – RobCo

0

这可能是短,没有任何警告

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