init 代码块与初始化顺序
使用 init 代码块,并理解属性与代码块的初始化顺序。
init 代码块与初始化顺序 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。
什么是 init 块
init { } 块包含实例构造时运行的代码。它是主构造函数逻辑的一部分。
简单的 init 块
init 块会在构造期间运行,并按照源代码顺序在属性初始化器之后执行。
class Logger(val name: String) {
init {
println("Constructed Logger("$name")")
}
}
fun main() {
val l = Logger("auth")
}在 init 中进行验证
请在 init 中使用 require / check,以便在构造时强制执行不变量。
class Percentage(val value: Int) {
init {
require(value in 0..100) { "value must be 0..100, was $value" }
}
}
fun main() {
println(Percentage(75).value)
// Percentage(150) // throws IllegalArgumentException
}多个 init 块
您可以拥有多个 init 块;它们会按照源代码顺序执行,并与属性初始化器交错运行。
class Demo(val x: Int) {
init { println("First init, x=$x") }
val doubled = x * 2
init { println("Second init, doubled=$doubled") }
}
fun main() {
Demo(5)
}属性初始化器与 init 顺序
属性初始化器和 init 块会按照源代码从上到下的顺序运行。属性必须先完成赋值,之后才能使用。
class Order {
val createdAt = System.currentTimeMillis()
init { println("created at $createdAt") }
val nextId = 1
init { println("next id = $nextId") }
}
fun main() {
Order()
}无法在属性初始化前使用属性
如果在属性初始化器运行前引用属性,就会产生编译错误。
class Bad {
init {
// println(name) // ERROR: name not yet initialized
}
val name = "after init"
}
fun main() { Bad() }计算派生属性
请使用 init 块计算依赖多个构造函数参数的派生状态。
class Rectangle(val width: Int, val height: Int) {
val area: Int
init {
area = width * height
}
}
fun main() {
val r = Rectangle(4, 5)
println("area = ${r.area}") // 20
}副作用:日志记录
对于日志记录、分配或注册等非简单初始化工作,请使用 init。
class Service(val name: String) {
init {
println("[BOOT] starting service '$name'")
}
}
fun main() {
Service("auth")
Service("payments")
}子类的 init 顺序
父类的 init 会在子类的 init 之前运行。每个类自身的属性都会按照源代码顺序初始化。
open class Base {
init { println("Base init") }
}
class Sub : Base() {
init { println("Sub init") }
}
fun main() { Sub() }避免在 init 中执行繁重逻辑
运行时间较长的 init 块会拖慢每次构造。如果初始化成本较高,请考虑延迟初始化或工厂函数。
class Heavy(val n: Int) {
val data: List<Int> by lazy { (1..n).toList() }
}
fun main() {
val h = Heavy(1_000_000)
println("Created without computing data")
println("First element: ${h.data[0]}") // now data initializes
}组合 init 与次构造函数
次构造函数会委托给主构造函数;init 块会作为主构造路径的一部分运行。
class Box(val content: String) {
init { println("init for '$content'") }
constructor(): this("empty") { println("secondary done") }
}
fun main() {
Box()
}快速检查
Kotlin 类中多个 init 块和属性初始化器的执行顺序是什么?
回顾
init 块包含构造期间的逻辑,包括验证、派生属性和副作用。多个块会按照源代码顺序执行,并与属性初始化器交错运行。请避免在 init 中执行繁重工作,改用 lazy 或工厂函数。
常见问题解答
「init 代码块与初始化顺序」课时是免费的吗?
是的 — 「init 代码块与初始化顺序」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。
「init 代码块与初始化顺序」这节课中我会学到什么?
使用 init 代码块,并理解属性与代码块的初始化顺序。 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Kotlin Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「init 代码块与初始化顺序」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Kotlin Academy 课中编写并运行代码吗?
能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 主构造函数与属性参数
- init 代码块与初始化顺序
- 使用 field 自定义 Getter 与 Setter
- lateinit 与延迟初始化