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

    • 简单属性初始化(直接使用属性初始化器)。
    • 与次构造函数逻辑高度耦合时(优先将逻辑放在次构造函数体内)
相关推荐
程序员-珍44 分钟前
关于协程相关问题
android·安卓
wdfk_prog1 小时前
Wi-Fi Direct 教程 04:Interface 协议子系统初始化——WPA/EAPOL、WPS、DPP/NAN、GAS 与 P2P callback
android·运维·服务器·ubuntu·p2p·wps·wifi-direct
警醒与鞭策9 小时前
【无标题】
android·unity·性能优化·游戏引擎·perforce
传奇开心果编程11 小时前
【Jetpack Compose进阶学与练】第14课:系列收尾复习总结;Compose项目常见坑点汇总;学习路线与后续学习方向
android·学习·ui·kotlin·android jetpack
李游Leo14 小时前
《HarmonyOS 7 精准碰一碰跨设备协作开发实战》07:异常恢复、状态机与CrossDrop工程收尾【鸿蒙心迹】
android·harmonyos
方白羽17 小时前
Android APK安全防护
android·安全·apk
小黄人软件17 小时前
AndroidStudio老项目 macOS运行BlueTooth蓝牙串口助手(Android+Studio源码).rar
android·macos
00后程序员张17 小时前
苹果App Store上架指南:费用、原理与步骤详解
android·ios·小程序·https·uni-app·iphone·webview
天神哥哥啊17 小时前
cocos联调注意事项-安卓
android
TDengine (老段)17 小时前
TDengine TSDB 实战排障四(升级与兼容)
android·java·大数据·数据库·物联网·时序数据库·tdengine