我熟悉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的尝试是这样的:
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)
我很想知道我做错了什么。
发布于 2018-01-18 10:14:33
尝试在field
中使用get()
关键字
private var mySecret: String? = null
get() {
if (field == null) initMySecret()
return field
}
一般来说,field
允许直接访问您的值,而无需调用get
,几乎与您的get
示例中的方式相同。更多信息可以在文档中找到。
发布于 2018-01-18 10:16:14
您所面临的问题是,当您以这种方式调用您的属性时,将再次调用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博士上看到
https://stackoverflow.com/questions/48327734
复制相似问题