简体   繁体   English

Kotlin `object` 初始化顺序导致意外的 null 实例

[英]Kotlin `object` initialization order leads to unexpected null instance

Consider the following code:考虑以下代码:

sealed class DataType<T : Any> {
    abstract fun inputToType(input: String): T
    abstract fun typeToSql(value: T): String

    companion object {
        val all = listOf(StringDt, LongDt)
    }
}

object StringDt : DataType<String>() {
    override fun inputToType(input: String) = input
    override fun typeToSql(value: String) = "\"${value}\""
}

object LongDt : DataType<Long>() {
    override fun inputToType(input: String) = input.toLong()
    override fun typeToSql(value: Long) = value.toString()
}

val dataTypeList = listOfNotNull(StringDt, LongDt)

println(dataTypeList)
println(DataType.all)

Things to consider:需要考虑的事项:

  • object as per documentation (and my understanding as well) is singleton and always instantiated object根据文档(以及我的理解)是 singleton 并且总是实例化
  • the two objects ( StringDt and LongDt ) are quite similar这两个对象( StringDtLongDt )非常相似

The result of println(DataType.all) shows that one of the objects are not initialized. println(DataType.all)的结果显示其中一个对象未初始化。 How is that possible?这怎么可能? I would expect all the list elements to be initialized.我希望所有列表元素都被初始化。

IntelliJ version: CE 2020.2 Kotlin plugin version: 1.4.0-release-IJ2020.2-1 IntelliJ 版本:CE 2020.2 Kotlin 插件版本:1.4.0-release-IJ2020.2-1

Here's a running example which shows that the static list has a null element, while the non-static one contains both objects initialized.这是一个运行示例,显示 static 列表有一个 null 元素,而非静态列表包含两个已初始化的对象。

It happens due to cyclical static initializations.这是由于循环 static 初始化而发生的。 It's pretty hard to explain this problem in two words but you can read about it here .很难用两个词来解释这个问题,但您可以在此处阅读相关内容。

To fix this behavior you can change all initialization like this:要修复此行为,您可以像这样更改all初始化:

val all by lazy { listOf(StringDt, LongDt) }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM