Kotlin 构造函数 #

一、主构造函数 #

1.1 基本语法 #

kotlin
class Person(val name: String, var age: Int)

1.2 显式 constructor 关键字 #

kotlin
class Person constructor(val name: String, var age: Int)

1.3 构造函数参数 #

kotlin
// val 参数:只读属性
// var 参数:可变属性
// 无修饰符:仅构造参数
class Person(
    val name: String,    // 属性
    var age: Int,        // 属性
    id: Int              // 仅参数
) {
    val idString = "ID: $id"
}

1.4 默认参数 #

kotlin
class Person(
    val name: String = "Unknown",
    var age: Int = 0
)

val p1 = Person()
val p2 = Person("Kotlin")
val p3 = Person("Kotlin", 10)
val p4 = Person(age = 10)

二、init 块 #

2.1 初始化代码 #

kotlin
class Person(val name: String, var age: Int) {
    init {
        println("Initializing Person")
        require(age >= 0) { "Age cannot be negative" }
    }
}

2.2 多个 init 块 #

kotlin
class Person(val name: String) {
    init {
        println("First init: $name")
    }
    
    val upperName = name.uppercase()
    
    init {
        println("Second init: $upperName")
    }
}

2.3 初始化顺序 #

kotlin
class Example {
    val a = 1.also { println("a = $it") }
    
    init {
        println("First init")
    }
    
    val b = 2.also { println("b = $it") }
    
    init {
        println("Second init")
    }
}

// 输出顺序:
// a = 1
// First init
// b = 2
// Second init

三、次构造函数 #

3.1 基本语法 #

kotlin
class Person(val name: String, var age: Int) {
    constructor(name: String) : this(name, 0) {
        println("Secondary constructor")
    }
}

3.2 多个次构造函数 #

kotlin
class Person(val name: String, var age: Int) {
    constructor(name: String) : this(name, 0)
    
    constructor(age: Int) : this("Unknown", age)
    
    constructor() : this("Unknown", 0)
}

val p1 = Person("Kotlin", 10)
val p2 = Person("Kotlin")
val p3 = Person(10)
val p4 = Person()

3.3 初始化顺序 #

kotlin
class Person(val name: String, var age: Int) {
    init {
        println("Init block")
    }
    
    constructor(name: String) : this(name, 0) {
        println("Secondary constructor body")
    }
}

val p = Person("Kotlin")
// 输出:
// Init block
// Secondary constructor body

四、私有构造函数 #

4.1 单例模式 #

kotlin
class Singleton private constructor() {
    companion object {
        val instance: Singleton by lazy { Singleton() }
    }
}

val singleton = Singleton.instance

4.2 工厂模式 #

kotlin
class User private constructor(val id: Int, val name: String) {
    companion object {
        fun create(id: Int, name: String): User {
            return User(id, name)
        }
        
        fun createGuest(): User {
            return User(0, "Guest")
        }
    }
}

val user = User.create(1, "Kotlin")
val guest = User.createGuest()

五、构造函数参数详解 #

5.1 可空参数 #

kotlin
class Person(
    val name: String,
    val email: String? = null
)

val p1 = Person("Kotlin")
val p2 = Person("Kotlin", "kotlin@example.com")

5.2 默认值表达式 #

kotlin
class Person(
    val name: String,
    val createdAt: Long = System.currentTimeMillis()
)

val p = Person("Kotlin")

5.3 函数参数 #

kotlin
class Button(
    val text: String,
    val onClick: () -> Unit = {}
)

val button = Button("Click") {
    println("Clicked!")
}

六、继承与构造函数 #

6.1 调用父类构造函数 #

kotlin
open class Person(val name: String)

class Student(name: String, val grade: Int) : Person(name)

// 或
class Student(name: String, val grade: Int) : Person(name.uppercase())

6.2 次构造函数调用父类 #

kotlin
open class Person(val name: String) {
    constructor(name: String, age: Int) : this(name)
}

class Student : Person {
    constructor(name: String) : super(name)
    
    constructor(name: String, age: Int) : super(name, age)
}

七、数据类构造函数 #

7.1 数据类要求 #

kotlin
// 主构造函数至少有一个参数
data class User(val id: Int, val name: String)

// 参数必须是 val 或 var
// data class Invalid(id: Int)  // 错误

7.2 copy 函数 #

kotlin
data class User(val id: Int, val name: String, val email: String)

val user = User(1, "Kotlin", "kotlin@example.com")
val updated = user.copy(name = "Updated")
// User(id=1, name=Updated, email=kotlin@example.com)

八、实战示例 #

8.1 配置类 #

kotlin
class Config private constructor(
    val host: String,
    val port: Int,
    val ssl: Boolean
) {
    class Builder {
        private var host: String = "localhost"
        private var port: Int = 8080
        private var ssl: Boolean = false
        
        fun host(host: String) = apply { this.host = host }
        fun port(port: Int) = apply { this.port = port }
        fun ssl(ssl: Boolean) = apply { this.ssl = ssl }
        
        fun build(): Config {
            return Config(host, port, ssl)
        }
    }
    
    companion object {
        fun builder() = Builder()
    }
}

val config = Config.builder()
    .host("example.com")
    .port(443)
    .ssl(true)
    .build()

8.2 验证构造 #

kotlin
class Email private constructor(val value: String) {
    companion object {
        fun of(value: String): Email? {
            return if (value.contains("@")) {
                Email(value)
            } else {
                null
            }
        }
    }
}

val email = Email.of("kotlin@example.com")  // Email
val invalid = Email.of("invalid")           // null

8.3 延迟初始化 #

kotlin
class Service(val config: Config) {
    private lateinit var connection: Connection
    
    fun connect() {
        connection = Connection(config)
    }
    
    fun isConnected(): Boolean {
        return ::connection.isInitialized
    }
}

九、最佳实践 #

9.1 优先使用主构造函数 #

kotlin
// 推荐
class Person(val name: String, var age: Int)

// 不推荐
class Person {
    var name: String = ""
    var age: Int = 0
    
    constructor(name: String, age: Int) {
        this.name = name
        this.age = age
    }
}

9.2 使用默认参数替代重载 #

kotlin
// 推荐
class Person(val name: String = "Unknown", var age: Int = 0)

// 不推荐
class Person {
    constructor(name: String, age: Int)
    constructor(name: String) : this(name, 0)
    constructor() : this("Unknown", 0)
}

9.3 验证参数 #

kotlin
class Person(val name: String, var age: Int) {
    init {
        require(name.isNotBlank()) { "Name cannot be blank" }
        require(age >= 0) { "Age cannot be negative" }
    }
}

十、总结 #

构造函数要点:

类型 说明
主构造函数 类头部定义,首选
次构造函数 constructor 关键字,委托主构造函数
init 块 初始化代码
默认参数 减少构造函数重载

下一步,让我们学习 继承

最后更新:2026-03-27