Kotlin枚举类init块访问伴生对象变量报‘Variable must be initialized’求解
枚举类init块访问伴生对象变量报错的原因与解决办法
你这段枚举类代码的核心问题是枚举常量的初始化时机早于伴生对象的初始化,导致init块执行时,伴生对象里的propertyToEnum还未完成初始化,从而触发编译器错误。
具体原因
Kotlin枚举类的初始化顺序遵循以下规则:
- 枚举类的所有常量(ONE、TWO、THREE)会在类加载阶段优先被实例化,每个常量对应的
init块也会同步执行。 - 伴生对象的初始化操作,要等到所有枚举常量完全实例化之后才会开始。
所以当init块尝试写入propertyToEnum时,这个映射表还没被创建,编译器自然会提示“变量未初始化”。
两种可行的解决办法
方案一:在伴生对象中一次性填充映射表
去掉枚举类的init块,直接在伴生对象里通过遍历枚举常量来构建映射表。这种方案逻辑集中,结构更清晰:
enum class Example(val property: Int) { ONE(333), TWO(444), THREE(555); companion object { private val propertyToEnum = mutableMapOf<Int, Example>().apply { Example.values().forEach { enum -> this[enum.property] = enum } } fun reverseLookup(property: Int): Example? { return propertyToEnum[property] } } }
方案二:用lazy延迟初始化映射表
通过by lazy委托让propertyToEnum在第一次被访问时完成初始化,确保枚举常量的init块执行时能正常使用:
enum class Example(val property: Int) { ONE(333), TWO(444), THREE(555); init { propertyToEnum[property] = this } companion object { private val propertyToEnum by lazy { mutableMapOf<Int, Example>() } fun reverseLookup(property: Int): Example? { return propertyToEnum[property] } } }
方案对比
- 方案一更推荐:初始化逻辑集中在伴生对象,避免依赖初始化顺序的潜在风险,代码可读性更好。
- 方案二更贴近你原本的实现思路,但依赖
lazy的初始化特性,适合需要保留init块逻辑的场景。
内容的提问来源于stack exchange,提问作者Adam Burley
相关产品推荐
相关产品推荐

