Kotlin 的 ‌init 代码块‌

Kotlin 的 ‌**init 代码块**‌是类初始化逻辑的核心部分,用于在对象创建时执行特定的初始化操作。以下是其核心知识点和典型用法:


基本特性

  1. 执行时机‌:

    • 在类实例化时,‌主构造函数调用后立即执行‌。
    • 与属性初始化器按代码中的‌声明顺序‌执行。
  2. 主要用途‌:

    • 初始化需要复杂逻辑的属性。
    • 验证构造函数参数的有效性。
    • 执行对象创建时的必要操作(如资源加载、日志记录)。

语法结构

kotlin 复制代码
class MyClass(param: String) {
    // 属性初始化器(直接赋值)
    val simpleProperty = param.uppercase()

    // init 代码块
    init {
        require(param.isNotEmpty()) { "参数不能为空" } // 参数校验
        println("对象已创建,参数为:$param")
    }

    // 另一个 init 块(按声明顺序执行)
    init {
        println("第二个初始化块")
    }
}

执行顺序

  1. 主构造函数参数 ‌ → ‌属性初始化器 ‌ → ‌**init‌ → ‌次构造函数体**‌(若有)。
  2. 多个 init 块按‌代码中的声明顺序‌依次执行。
  3. 若存在‌次构造函数 ‌,所有 init 块和属性初始化器会在次构造函数体之前执行。

示例‌:

kotlin 复制代码
class Person(val name: String) {
    val firstProperty = "第一个属性".also(::println)

    init {
        println("第一个 init 块")
    }

    val secondProperty = "第二个属性".also(::println)

    init {
        println("第二个 init 块")
    }

    constructor(name: String, age: Int) : this(name) {
        println("次构造函数体") // 最后执行
    }
}

// 输出:
// 第一个属性
// 第一个 init 块
// 第二个属性
// 第二个 init 块
// 次构造函数体

典型使用场景

1. ‌参数校验

javascript 复制代码
class User(name: String) {
    init {
        require(name.isNotBlank()) { "用户名不能为空" }
    }
}

2. ‌复杂属性初始化

kotlin 复制代码
class DatabaseConfig(url: String) {
    val connectionTimeout: Int

    init {
        connectionTimeout = parseTimeout(url) // 调用函数计算值
    }

    private fun parseTimeout(url: String): Int { /* ... */ }
}

3. ‌资源初始化

arduino 复制代码
class FileLoader(path: String) {
    private val file: File

    init {
        file = File(path)
        file.createNewFile() // 创建文件
    }
}

注意事项

  1. 避免访问未初始化的属性‌:

    kotlin 复制代码
    class Demo {
        val a = 1
        init {
            println(a)  // 正确:输出 1
            println(b)  // 错误!此时 b 尚未初始化
        }
        val b = 2
    }
  2. 与次构造函数的关系‌:

    • 所有 init 块和属性初始化器会在次构造函数体‌之前‌执行。
    • 次构造函数必须直接或间接委托给主构造函数。
    kotlin 复制代码
    class Person(val name: String) {
        init { println("主构造逻辑") }
    
        constructor() : this("默认名称") {
            println("次构造逻辑") // 在 init 块之后执行
        }
    }
  3. 异常处理‌:

    • init 块中可抛出异常,中断对象创建:
    arduino 复制代码
    class Validator(rule: String) {
        init {
            if (rule.contains("invalid")) throw IllegalArgumentException("非法规则")
        }
    }

与 Java 初始化块的对比

这个不是Java的 static{} 相当于是Java的 {} 构造代码块

特性 Kotlin init Java 实例初始化块
执行时机 主构造函数之后 构造函数之前
与构造函数关系 属于主构造函数的一部分 独立于构造函数
多个块执行顺序 按代码顺序执行 按代码顺序执行
参数访问 直接使用主构造函数参数 需通过构造函数参数赋值给字段

总结

  • 使用 init 的场景:

    • 需要‌在主构造函数中嵌入复杂逻辑‌时。
    • 确保对象创建时‌属性合法 ‌或‌资源就绪‌。
  • 避免 init 的场景:

    • 简单属性初始化(直接使用属性初始化器)。
    • 与次构造函数逻辑高度耦合时(优先将逻辑放在次构造函数体内)
相关推荐
还鮟3 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡4 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi005 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil6 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你6 小时前
Android View的绘制原理详解
android
移动开发者1号9 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号9 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
ii_best14 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk14 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭19 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin