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 的场景:

    • 简单属性初始化(直接使用属性初始化器)。
    • 与次构造函数逻辑高度耦合时(优先将逻辑放在次构造函数体内)
相关推荐
DogDaoDao4 小时前
Android 硬件编码器参数完全指南:MediaCodec 深度解析
android·音视频·视频编解码·h264·硬编码·视频直播·mediacodec
JohnnyDeng945 小时前
Android 自定义 View:Canvas 绘图与事件分发深度解析
android
Android小码家8 小时前
Framework之Launcher小窗开发
android·framework·虚拟屏·小窗
赏金术士8 小时前
第七章:状态管理实战与架构总结
android·ui·kotlin·compose
颂love10 小时前
MySQL的执行流程
android·数据库·mysql
云起SAAS14 小时前
抖音小游戏源码 - 消消乐 | 含激励广告+成就系统 | 开箱即用商业级消除游戏模板
android·游戏·广告联盟·看激励广告联盟流量主·抖音小游戏源码 - 消消乐
大貔貅喝啤酒15 小时前
基于Windows下载安装Android Studio 3.3.2版本教程(2026详细图文版)
android·java·windows·android studio
程序员码歌15 小时前
OpenSpec 到 Superpowers:AI 编码从说清到做对
android·前端·人工智能
2501_9151063216 小时前
深入解析无源码iOS加固原理与方案,保护应用安全
android·安全·ios·小程序·uni-app·cocoa·iphone
黄林晴19 小时前
重磅官宣:Android UI 开发正式进入 Compose-first 时代
android·google io