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

Kotlin父类B初始化块与构造函数属性值差异问题咨询

问题解析:父类init块与构造函数中属性值差异原因

我无法理解以下代码中,父类B的init{}块里i和s的值分别为0和null,但B的第二个构造函数中这两个值却是200和param2,请帮忙解释原因。

代码示例

class A(override var i: Int, override var s: String) : B(200, "param2","param3") {
        init {
           println(i)
           println(s)
        }
 }


open class B(open var i: Int, open var s: String) {
    init {
        println("class B init")
        println("i in init B2 is $i")
        println("s in init B2 is $s")
    }


   constructor(i: Int, s: String, s2: String) : this(i, s) {
        println("second constructor B")
        println(" i = $i in second constructor")
        println(" s = $s in second constructor")
        println(" s2 = $s2 in second constructor")
    }

}

    
fun main() {
   val ins2 = A(500, "500S") 
}

运行结果

class B init
i in init B2 is 0
s in init B2 is null
second constructor B
 i = 200 in second constructor
 s = param2 in second constructor
 s2 = param3 in second constructor
500
500S

原因解释

  • 子类A通过override var重写了父类B的i和s属性,这导致父类中对这两个属性的访问,在子类实例化时会指向子类的对应属性,而非父类自身的属性。
  • 实例化A的流程:调用A的构造函数后,会先触发父类B的第二个构造函数,该构造函数通过: this(i,s)调用父类主构造函数。
  • 父类主构造函数执行时会优先运行init块,但此时子类A的i和s还未完成初始化(子类的属性赋值逻辑在父类初始化完成后才会执行),所以init块中访问的是子类A里被重写属性的默认值:Int类型默认0,String类型默认null。
  • 父类的第二个构造函数在init块执行完毕后才会运行,这里的i和s是构造函数接收的参数值(也就是传入的200和param2),和子类的重写属性无关,所以能正确显示传入的参数内容。
  • 父类初始化完成后,子类A的属性才会被赋值为500和"500S",因此A的init块会输出这两个最终值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:21:38