在Kotlin中使用Singleton的StackOverflowError

谁能告诉,为什么我得到一个java.lang.StackOverflowError使用这个Kotlin类? 第41行是if (instance == null) {

 class TokenHelper protected constructor() { var token: String? = null var appId: String? = null var installationId: String? = null var userId: String? = null companion object { var instance: TokenHelper? = null get() { if (instance == null) { instance = TokenHelper() } return instance } } } 

堆栈跟踪:

 04-11 19:07:42.188 16142-16142/com.foo.bar.debug E/AndroidRuntime: FATAL EXCEPTION: main Process: com.foo.bar.debug, PID: 16142 java.lang.StackOverflowError: stack size 8MB at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:0) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41 04-11 19:07:42.271 16142-16142/com.foo.bar.debug D/Error: ERR: exClass=java.lang.StackOverflowError 04-11 19:07:42.271 16142-16142/com.foo.bar.debug D/Error: ERR: exMsg=stack size 8MB 04-11 19:07:42.271 16142-16142/com.foo.bar.debug D/Error: ERR: file=TokenHelper.kt 04-11 19:07:42.271 16142-16142/com.foo.bar.debug D/Error: ERR: class=com.foo.bar.helper.TokenHelper$Companion 04-11 19:07:42.271 16142-16142/com.foo.bar.debug D/Error: ERR: method=getInstance line=0 04-11 19:07:42.282 16142-16142/com.foo.bar.debug D/Error: ERR: stack=java.lang.StackOverflowError: stack size 8MB at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:0) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance(TokenHelper.kt:41) at com.foo.bar.helper.TokenHelper$Companion.getInstance( 04-11 19:07:42.283 16142-16142/com.foo.bar.debug D/Error: ERR: TOTAL BYTES WRITTEN: 880768 04-11 19:07:45.527 16142-16142/com.foo.bar.debug D/Process: killProcess, pid=16142 04-11 19:07:45.528 16142-16142/com.foo.bar.debug D/Process: com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException:113 java.lang.ThreadGroup.uncaughtException:693 java.lang.ThreadGroup.uncaughtException:690 

Android Studio 2.0,Kotlin 1.0.1-2

改编自对原始答案的评论:

在Kotlin中,你并不需要所有的样板文件来声明单例。 在声明你的类的时候,简单地把它变成这样的object

 object TokenHelper { var token: String? = null var appId: String? = null var installationId: String? = null var userId: String? = null } 

然后如下访问它: TokenHelper.token或从Java TokenHelper.INSTANCE.getToken()

您正在递归调用instance getter方法。 改变你的getter定义来使用field来代替:

 var instance: TokenHelper? = null get() { if (field == null) { field = TokenHelper() } return field } 

文档的相关摘录如下:

Kotlin的课程不能有字段。 但是,使用自定义访问器时有时需要有后台字段。 为了这些目的,Kotlin提供了一个可以使用字段标识符访问的自动后台字段:

 var counter = 0 // the initializer value is written directly to the backing field set(value) { if (value >= 0) field = value } 

字段标识符只能用于属性的访问器中。