主构造函数是类最主要的、最简洁的构造方式,每个类最多只能有一个。
()
包裹参数。val
或 var
,直接将其声明为类的属性,这是 Kotlin 的一个重要语法糖。init
代码块中直接访问。constructor
关键字可以省略。示例代码:
// 主构造函数,将 username 和 age 直接声明为类的属性
class User(val username: String, var age: Int) {
// 主构造函数的参数 username 和 age 在这里可以直接使用
val isAdult: Boolean = age >= 18
}
// 使用主构造函数创建实例
val user = User("Alex", 25)
println("${user.username} is an adult: ${user.isAdult}") // 输出: Alex is an adult: true
当需要提供不同于主构造函数的初始化方式时(例如,接受不同类型的参数),可以使用次级构造函数。
constructor
关键字声明。this(...)
关键字直接或间接地代理(调用)到主构造函数。这确保了主构造函数中的初始化逻辑(包括 init
块和属性初始化)总是被执行。super()
)。示例代码:
class Person(val name: String) { // 1. 主构造函数
var age: Int = 0
init {
println("Init block called. Name is $name")
}
// 2. 次级构造函数,通过 this(name) 代理到主构造函数
constructor(name: String, age: Int) : this(name) {
println("Secondary constructor body called.")
this.age = age
}
}
// 使用次级构造函数创建实例
val person = Person("Bob", 30)
// 输出:
// Init block called. Name is Bob
// Secondary constructor body called.
init
初始化块init
块用于存放主构造函数的初始化逻辑,例如执行校验、打印日志等。
init
块是主构造函数的一部分。当实例被创建时,其中的代码会按顺序执行。init
块,它们会按照在类体中出现的顺序依次执行。init
块的执行时机在属性初始化之后、次级构造函数体执行之前。理解 Kotlin 类的初始化顺序至关重要。当通过次级构造函数创建实例时,其执行流程如下:
this(...)
代理)。init
块按照它们在代码中的书写顺序自顶向下执行。综合示例来演示顺序:
class Example(name: String) {
// 1. 属性初始化
val firstProperty = "First property: $name".also { println(it) }
// 2. 第一个 init 块
init {
println("First initializer block that prints ${name.uppercase()}")
}
// 3. 第二个属性初始化
val secondProperty = "Second property: ${name.length}".also { println(it) }
// 4. 第二个 init 块
init {
println("Second initializer block")
}
// 次级构造函数
constructor(name: String, id: Int): this(name) {
// 5. 次级构造函数体
println("Secondary constructor body with id: $id")
}
}
// 通过次级构造函数创建实例
val example = Example("Kotlin", 101)
/*
* 输出结果严格遵循初始化顺序:
* First property: Kotlin
* First initializer block that prints KOTLIN
* Second property: 6
* Second initializer block
* Secondary constructor body with id: 101
*/