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上可以看到关于懒惰的更多例子