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

Kotlin by lazy和lateinit的使用及区别

在 Kotlin 中,lateinitby lazy 都可以用来延迟初始化变量,但它们有不同的适用场景和使用方式。下面详细介绍它们的用法和区别。

1.lateinit

lateinit 关键字用于延迟初始化 可变属性 (var),主要用于那些在声明时不能立即初始化,但保证在使用前会完成初始化的属性。lateinit 只能用于非空的 可变变量,且只能用于 类的属性(不能用于局部变量或常量)。

使用场景

lateinit 通常用于 Android 的 ContextViewPresenter 等需要在声明时无法立即赋值,但稍后会赋值的情况。

示例代码
class Example {
    lateinit var text: String // 延迟初始化的变量

    fun initializeText() {
        text = "Hello, World!"
    }

    fun printText() {
        if (this::text.isInitialized) { // 检查是否已经初始化
            println(text)
        } else {
            println("text 未初始化")
        }
    }
}

fun main() {
    val example = Example()
    example.initializeText()
    example.printText() // 输出:Hello, World!
}
注意事项
  • 只适用于可变变量lateinit 只能用于 var 变量,不能用于 val
  • 非空类型lateinit 只能用于非空类型,不能用于原始数据类型(如 IntDouble 等)。
  • 是否初始化检查:可以使用 this::property.isInitialized 检查属性是否已初始化,避免直接访问未初始化的变量引发异常。

2. by lazy

by lazy 适用于 不可变属性 (val),它的初始化只会在第一次被访问时触发,且结果会被缓存下来,以后每次访问时都返回相同的值。by lazy 可以用来延迟初始化那些计算量大或依赖其他数据的属性,通常适用于线程安全的场景。by lazy本身是一种属性委托。属性委托的关键字是by。

使用场景

适合用来初始化 只读变量,比如配置文件加载、耗时计算结果等。

示例代码
class Example {
    val text: String by lazy {
        println("初始化 text")
        "Hello, Lazy!"
    }

    fun printText() {
        println(text) // 第一次访问时初始化
    }
}

fun main() {
    val example = Example()
    example.printText() // 输出:初始化 text\nHello, Lazy!
    example.printText() // 输出:Hello, Lazy!(不会再初始化)
}
注意事项
  • 只适用于只读变量by lazy 只能用于 val 变量,表示它是不可变的。
  • 线程安全by lazy 的默认模式是线程安全的(相当于 LazyThreadSafetyMode.SYNCHRONIZED),也可以选择其他模式,如 LazyThreadSafetyMode.PUBLICATIONLazyThreadSafetyMode.NONE
  • 延迟计算:只有在属性第一次被访问时才会初始化。

3. lateinitby lazy 的区别

特性lateinitby lazy
适用类型var 可变变量val 不可变变量
适用数据类型只能用于非空对象类型适用于任何类型,包括基础数据类型
初始化时机在使用前需要手动赋值第一次访问时自动初始化
初始化次数可以被多次赋值只会被初始化一次
线程安全性无内置的线程安全默认是线程安全的(可更改模式)
使用场景Android 中的 ContextView计算量大的只读变量,懒加载
是否可检查初始化状态可以使用 isInitialized 检查无法检查是否已初始化

总结

  • 使用 lateinit:适用于那些需要稍后赋值且会被多次修改的对象属性,比如 Android 中的 ContextView
  • 使用 by lazy:适用于那些不需要立即初始化,且一旦初始化后不再改变的只读属性,比如计算密集型或一次性加载的属性。
  • 一般来说的话,lateinit一定要记得初始化,不然后面会爆异常UninitializedPropertyAccessException

http://www.kler.cn/a/379077.html

相关文章:

  • ES + SkyWalking + Spring Boot:日志分析与服务监控(三)
  • 如果 MySQL 主库出现了问题,从库该何去何从呢?
  • 【AI】【提高认知】深度学习与反向传播:理解AI的基础
  • 二、应用层,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》
  • Python | Leetcode Python题解之第530题二叉搜索树的最小绝对差
  • Three.js简化 WebGL 的使用
  • qemu_imx6ul使用mount挂载Permission denied问题解决记录
  • 为什么要使用Golang以及如何入门
  • 【Linux】ProxySQL读写分离
  • 信息学科平台系统开发:基于Spring Boot的最佳实践
  • Android使用timer和thread实现定时器
  • 【数据结构】堆:建堆/向下调整/上向调整/堆排序/TOK问题
  • 数组、字符串、链表和队列的指针的定义
  • CQ社区版 v2024.10 | 支持k8s、helm部署!
  • SpringBoot中扩展Druid的过滤器实现完整的SQL打印
  • 学习笔记:黑马程序员JavaWeb开发教程(2024.10.27)
  • 心情追忆-AI分析报错
  • sklearn|机器学习:决策树(一)
  • 详解RabbitMQ三种队列类型
  • 两秒掌握git
  • laravel: Breeze 和 Blade, 登录 注册等
  • 使用 Elasticsearch 进行语义搜索
  • vue3-ref 和 reactive
  • Android Livedata源码解析
  • JVM问题排查分析
  • 探索开源语音识别的未来:高效利用先进的自动语音识别技术20241030