【问题标题】:Kotlin enum val is returning null, despite being set at compile time尽管在编译时设置了 Kotlin enum val,但它返回 null
【发布时间】:2021-10-22 06:15:18
【问题描述】:

我有一个包含多个字段的 Kotlin 枚举。其中一个字段 (enterableBoard) 是另一个枚举的值。在运行时,尽管已设置此 val 为 null。

我以前从未见过这样的事情,并且其他领域工作正常,即使是引用当前Item 的领域!我已经包含了完整的枚举定义,因为我不确定什么是相关的。

Item 枚举和一个值,其中 enterableBoard 意外地为 null 而不是 Board.SPACEX_EARLY_TREES

enum class Item(
    val chain: ItemChain,
    val tier: Int,
    @StringRes val title: Int,
    @DrawableRes val image: Int,
    val generatorMaxEnergy: Int = 0, 
    val enterableBoard: Board? = null,
    val mergeBonus: Pair<Item, Int>? = null, 
    val redeemable: Pair<InfoLong, Int>? = null
) {
    TREE_9(ItemChain.TREE, 9, R.string.item_tree9, R.drawable.item_tree9,
        generatorMaxEnergy = 50, enterableBoard = Board.SPACEX_EARLY_TREES)
}

Board枚举和相关值:

enum class Board(
    val campaign: Campaign,
    @StringRes val title: Int,
    @StringRes val description: Int,
    @DrawableRes val background: Int,
    @DrawableRes val image: Int,
    val unlockCost: Int,
    val template: List<Item>
) {
    SPACEX_EARLY_TREES(Campaign.SPACEX_EARLY, R.string.board_spacex_early_tree_title, R.string.board_spacex_early_tree_description,
        R.drawable.background5, R.drawable.background5, 0,
        listOf(Item.FRUITVEG_1, Item.FRUITVEG_2, Item.FRUITVEG_1))
}

这是enterableBoard 意外为空的屏幕截图:

补充说明:

  • 我尝试更改 TREE_9 中的其他值,并且它们都更新了,因此包含的定义肯定是正在使用的定义。
  • 尝试在代码中访问该字段时,该字段也为空。
  • Kotlin 版本 1.5.20。
  • Android Studio 2020.3.1 补丁 1。

【问题讨论】:

    标签: android kotlin enums


    【解决方案1】:

    我很确定这是因为您有互惠的参考。 Board 在其构造函数中引用 Item ,反之亦然。两个枚举类的成员之一在另一个之前实例化,因此对其他值的引用在引用它们时仍然为空。这是一种偷偷摸摸的方法,你可以通过做一些你不应该做的事情,比如调用 @ 987654322@ 来自构造函数的函数。

    基本上,枚举不能安全地相互引用,因为它们在实例化时是如何编译和行为的。编译器是否应该针对这种情况显示警告或错误?可能,但显然没有。

    以下是该问题的最小可重现示例:

    enum class Item (val board: Board) {
        X(Board.Y)
    }
    
    enum class Board(val item: Item) {
        Y(Item.X)
    }
    
    fun main() {
        Item.X
        println(Board.Y.item)
    }
    

    打印null,因为对Item.X的引用导致Item的成员首先被实例化,但是由于它的构造函数引用了Board,所以Board实际上首先被实例化并且使用仍然为空的Item.X引用。

    【讨论】:

    • 我认为你是对的,谢谢。我非常非常惊讶 Kotlin 在编译时没有给出某种错误。在我的情况下,我可以轻松更改模型,但我很好奇是否有办法实际修复它。
    猜你喜欢
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 2014-02-26
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多