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

Kotlin中init块内的name引用为何指向构造函数参数而非类属性

Kotlin中init块内的name引用为何指向构造函数参数而非类属性

哈哈,这个坑我刚学Kotlin的时候也踩过,当时盯着控制台输出愣了半天!咱们先把问题里的代码理清楚,方便一步步分析:

class InitOrderDemo(name: String) {
    init { 
        println("$name") 
    }
    val name = name + " " + "world"
}

fun main() {
    InitOrderDemo("hello") // 实际输出:hello
}

你遇到的问题核心就是Kotlin的实例初始化顺序,咱们对照规则拆解一下:

During the initialization of an instance, the initializer blocks are executed in the same order as they appear in the class body, interleaved with the property initializers

翻译成大白话就是:创建实例时,类体里的属性初始化代码和init块,是严格按照你写代码的先后顺序来执行的,谁在前谁先跑。

咱们一步步走一遍实例创建的流程:

  • 调用InitOrderDemo("hello")时,构造函数的参数name先被赋值为"hello",这个参数在整个初始化过程中都是能访问到的。
  • 接下来开始执行类体里的代码,第一个碰到的就是init块——这时候类里的val name属性还没开始初始化呢,它的定义在init块后面,得等init块执行完才会轮到它。
  • 所以init块里的println("$name"),编译器会在当前可用的作用域里找name,这时候只有构造函数传进来的那个参数name是可用的,自然就输出了"hello"。
  • 等init块跑完,才会执行val name = name + " world"这行:右边的name还是构造函数的参数,赋值完成后,类属性name才会变成"hello world",但这时候init块已经执行完了,你自然看不到这个值被打印出来。

要是把代码顺序调一下,把类属性name的定义放在init块前面:

class InitOrderDemo(name: String) {
    val name = name + " " + "world"
    init { 
        println("$name") 
    }
}

这时候就会先初始化类属性name(用构造函数参数拼接成"hello world"),然后init块里打印的就是类属性的name,输出就变成"hello world"了。

另外提个小细节:要是你想在init块里明确指定引用类属性,得用this.name,但如果类属性还没初始化(比如init块在它前面),调用this.name会直接抛UninitializedPropertyAccessException,所以这种场景下也不能这么用,必须等类属性初始化完成才行。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.09 03:03:04