Getter在Kotlin的无限递归
我对Java很熟悉,但是我和Kotlin一起工作很困难。
为了说明我的问题,下面是一些Java代码。 如果getter发现该字段为NULL,则在返回字段之前初始化该字段。
package test; public class InitFieldJava { private final static String SECRET = "secret"; private String mySecret; public String getMySecret() { if(mySecret == null) initMySecret(); return mySecret; } private void initMySecret() { System.out.println("Initializing Secret ...."); mySecret = SECRET; } public static void main(String[] args) { InitFieldJava field = new InitFieldJava(); System.out.println(field.getMySecret()); } }
我可以在Kotlin上面做些什么吗? 我在Kotlin的尝试是这样的:
package test class InitFieldKotlin { private val SECRET = "secret" private var mySecret: String? = null get() { if (mySecret == null) initMySecret() //Infinite Recursion!!! return mySecret } private fun initMySecret() { println("Initializing Secret ....") mySecret = SECRET } companion object { @JvmStatic fun main(args: Array) { val field = InitFieldKotlin() println(field.mySecret) } } }
我的问题是,这导致无限递归:
Exception in thread "main" java.lang.StackOverflowError at test.InitFieldKotlin.getMySecret(InitFieldKotlin.kt:7) at test.InitFieldKotlin.getMySecret(InitFieldKotlin.kt:7) at test.InitFieldKotlin.getMySecret(InitFieldKotlin.kt:7) at test.InitFieldKotlin.getMySecret(InitFieldKotlin.kt:7)
我会很高兴知道我做错了什么。
尝试在get()
使用field
关键字:
private var mySecret: String? = null get() { if (field == null) initMySecret() return field }
一般来说, field
允许直接访问你的值而不用调用get
,几乎和你的Java例子一样。 更多信息可以在文档中find。
你面临的问题是,当你这样调用你的属性时,getter将被再次调用。 而当你调用getter时,另一个getter被调用,依此类推,直到一个StackOverflow。
您可以通过@Google来解决此问题,并使用getter中的field
而不是属性名称:
if (field == null)initMySecret()
这样你就不会使用它的getter来访问这个属性。
但更重要的是: 为什么不使用延迟初始化 ? 如果variables是最终的,看起来是这样,你可以使用一个懒惰的val
这样,该字段不会是空的,所以你不必安全地调用它。 而且你不会使用样板代码,Kotlin可以为你做这个懒惰的初始化!
val mySecret: String by lazy { println("Initializing Secret. This print will be executed only once!") "SECRETE" //This value will be returned on further calls }
在Kotlin Docs上可以看到关于懒惰的更多例子