Kotlin 中的 Getter 中的无限递归



我熟悉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<String>) {
            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 示例中的方式相同。有关详细信息,请参阅文档。

您面临的问题是,当您以这种方式调用您的属性时,将再次调用 getter。当你调用getter时,另一个getter被调用,依此类推,直到StackOverflow。

您可以按照 @Google 所示修复此问题,并在 getter 中使用 field,而不是属性名称:

if (field == null)initMySecret()

这样,您将不会使用其getter访问该属性。


但更重要的是:为什么不使用延迟初始化?如果变量是最终的,并且似乎是最终的,则可以使用懒惰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
}

更多关于 Lazy 的例子可以在 Kotlin Docs 上看到

最新更新