当前位置: 首页 > news >正文

深入解析:Kotlin 中companion object {} 什么时候触发

在 Kotlin 中,companion object 的初始化触发时机是一个重要但容易被忽视的细节。以下是详细的解释:

1. 基本触发时机

companion object 的初始化发生在:

  • 首次访问该类时(无论是访问伴生对象成员、创建类实例,还是通过反射访问类)

  • 类似于 Java 的静态初始化块,但更灵活

  • class MyClass {
    companion object {
    init {
    println("Companion object 初始化!")
    }
    val CONST = "Hello"
    }
    }fun main() {
    println("程序启动")
    MyClass.CONST // 第一次访问 MyClass 时触发初始化
    }

 输出

程序启动
Companion object 初始化!

2. 具体触发场景

以下操作都会触发 companion object 初始化:

(1) 直接访问伴生对象成员

MyClass.CONST          // 触发
MyClass.Companion      // 触发

(2) 创建类实例

val obj = MyClass()    // 触发

(3) 通过反射访问类

MyClass::class          // 触发(Kotlin 反射)

(4) 访问类的其他声明

MyClass::class          // 触发(Kotlin 反射)

3. 不会触发的情况

以下操作不会触发初始化:

// 仅声明类型(未实际访问)
val clazz: Class = MyClass::class.java// 作为类型参数(未实例化或访问)
fun process(clazz: Class<*>) {}
process(MyClass::class.java) // 不会触发

4. 与 Java 静态初始化的对比

特性Kotlin companion objectJava static 块
初始化时机首次访问类时类加载时
懒加载是(按需初始化)否(类加载时强制初始化)
线程安全是(JVM 保证)

5. 实际应用中的注意事项

(1) 性能优化
class HeavyInitialization {
companion object {
val HEAVY_RESOURCE = loadResource() // 避免在伴生对象中放重型初始化
}
}// 改为懒加载
class BetterApproach {
companion object {
val heavyResource by lazy { loadResource() }
}
}
(2) 循环依赖问题
class A {
companion object {
val VALUE = B.VALUE // 如果 B 的伴生对象也依赖 A,会导致栈溢出
}
}class B {
companion object {
val VALUE = A.VALUE
}
}

解决方案:使用 lazy 延迟初始化

class A {
companion object {
val VALUE by lazy { B.VALUE }
}
}

6. 验证示例

class Test {
companion object {
init { println("伴生对象初始化") }
}init { println("类实例初始化") }
}fun main() {
println("阶段1")
Test::class // 仅访问 KClass,不触发println("阶段2")
Test.Companion // 触发初始化println("阶段3")
Test() // 伴生对象已初始化,不会再次触发
}

输出

阶段1
阶段2
伴生对象初始化
阶段3
类实例初始化

总结

  • companion object 在首次真正使用类时初始化(懒加载)
  • 比 Java 的静态初始化更灵活,但逻辑相似
  • 适合存放类级别的常量、工厂方法等
  • 避免在伴生对象中直接进行重型操作,建议用 by lazy

http://www.gsyq.cn/news/16962.html

相关文章:

  • libopenssl-1_0_0-devel-1.0.2p RPM 包安装教程(openSUSE/SLES x86_64)​
  • API异常信息如何实时发送到钉钉 - 详解
  • 实用指南:解决 xmlsec.InternalError: (-1, ‘lxml xmlsec libxml2 library version mismatch‘)
  • 高质量同人动画整理回顾记录的方式
  • 加拿大加密货币牌照:合规化加速数字资产成功
  • 【Hexo】4.Hexo 博客文章进行加密 - 实践
  • 思考的动力
  • 星闪开发之Server-Client 指令交互控制OLED灯案例 - 教程
  • Baklib内容中台AI重构智能服务 - 实践
  • 计算机网络学习分享-0
  • 预科02git使用
  • 预科01Python学习
  • 实用指南:用PyTorch从零开始编写DeepSeek-V2
  • 博客迁移到CSDN!!!
  • 手动实现一个C++绑定Lua脚本的库
  • 图解C++智能指针的循环引用
  • 详细介绍:在机器视觉测量和机器视觉定位中,棋盘格标定如何影响精度
  • 题解:P11219 【MX-S4-T3】「yyOI R2」youyou 的序列 II
  • 前端HTML contenteditable 属性使用指南 - 教程
  • C++ list数据删除、list资料访问、list反转链表、list数据排序
  • DP分析黑科技——闫氏DP分析法
  • MUGEN游戏引擎等一系列相关杂谈
  • # 20232313 2025-2026-1 《网络与系统攻防技术》实验一实验报告 - 20232313
  • 完整教程:【无标题】
  • vector使用中的一个小问题
  • 一生一芯学习:PA2:输入输出
  • 深入解析:人工智能-Chain of Thought Prompting(思维链提示,简称CoT)
  • 年龄排序
  • 二分图最大匹配 输出具体方案
  • Success of Europa