You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin子类参数非空却为null?添加init块恢复正常的原因

问题原因解析:Kotlin类初始化顺序导致的成员变量未初始化问题

这本质是Kotlin父类与子类的初始化执行顺序问题,结合你描述的场景,具体逻辑如下:

核心执行顺序梳理

当创建ComplexSortingButton实例时,代码的执行流程是固定的:

  1. 先调用父类SortingButton的构造函数,执行父类的init块。
  2. 父类init块中调用onCreate(),此时子类的重写方法会被执行,但子类的成员变量(包括evaluator)还未完成初始化。
  3. 父类构造全部完成后,才会初始化子类的成员变量(将构造传入的evaluator参数赋值给成员变量),最后执行子类自己的init块。

对应你的两种场景

场景1:子类无自身init块调用onCreate

此时只有父类init块触发的onCreate调用,这个调用发生在子类evaluator成员变量赋值之前——因为子类成员初始化是父类构造完成后的步骤。所以重写的onCreate里拿到的evaluator是默认的null,哪怕你构造时传了非空值。

对应的简化代码示例:

open class SortingButton(context: Context) : Button(context) {
    init {
        onCreate() // 父类init先调用onCreate
    }

    open fun onCreate() {}
}

class ComplexSortingButton(context: Context, val evaluator: Evaluator?) : SortingButton(context) {
    override fun onCreate() {
        super.onCreate()
        println(evaluator) // 此时evaluator还未被赋值,输出null
    }
}

场景2:子类添加init块调用onCreate

子类的init块是在父类构造完成、子类成员变量赋值完成后执行的。此时调用onCreate,evaluator已经被构造参数赋值为非空值,所以重写方法里能拿到正确的非空对象。

对应的简化代码示例:

class ComplexSortingButton(context: Context, val evaluator: Evaluator?) : SortingButton(context) {
    init {
        onCreate() // 子类init在成员赋值后调用,此时evaluator已有值
    }

    override fun onCreate() {
        super.onCreate()
        println(evaluator) // 输出构造传入的非空值
    }
}

额外注意

在父类的构造函数或init块中调用可重写的方法是不推荐的危险操作,因为子类此时还未完成初始化,很容易出现这种未初始化成员的问题,甚至引发崩溃。更合理的做法是让子类自行在合适的时机(比如自身init块、Android的onFinishInflate等生命周期方法)调用初始化逻辑,而非依赖父类的提前调用。

内容的提问来源于stack exchange,提问作者Owlon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 11:03:19