Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?

简介: **Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点

在Kotlin中,by lazylateinit 都是用于延迟初始化的手段,但它们各自有不同的用法和特点。下面详细讨论它们的作用和区别。

1. by lazy

作用

by lazy 是一种委托属性,用于延迟初始化一个只读属性。属性在第一次访问时才会被初始化,并且初始化操作只会执行一次。

用法

语法:val property: Type by lazy { initializer }

lazy 的默认线程安全模式是 LazyThreadSafetyMode.SYNCHRONIZED,它确保多线程环境下属性只会被初始化一次。

示例

val myValue: String by lazy {
    println("Computed only once")
    "Hello, World!"
}

// 第一次访问 myValue,会触发初始化代码块执行
println(myValue) // 输出: "Computed only once" 和 "Hello, World!"
// 之后的访问不会重复执行初始化代码块
println(myValue) // 输出: "Hello, World!"

惰性线程安全模式

  • LazyThreadSafetyMode.SYNCHRONIZED:默认值,确保多线程环境下属性只能被初始化一次。
  • LazyThreadSafetyMode.PUBLICATION:允许多个线程在同一时间初始化,但只使用第一个完成的结果。
  • LazyThreadSafetyMode.NONE:不进行任何同步,适用于单线程环境。

示例

val valueSynchronized: String by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
    "Synchronized"
}

val valuePublication: String by lazy(LazyThreadSafetyMode.PUBLICATION) {
    "Publication"
}

val valueNone: String by lazy(LazyThreadSafetyMode.NONE) {
    "None"
}

2. lateinit

作用

lateinit 是一种延迟初始化的关键字,用于延迟初始化一个 var 可变属性。属性类型必须是非空的且不能是原始类型(如 Int, Double)。

用法

语法:lateinit var property: Type

lateinit 属性不能有自定义的 getter 和 setter,必须在使用之前显式初始化,否则会抛出 UninitializedPropertyAccessException

示例

lateinit var myValue: String

fun initialize() {
    myValue = "Hello, World!"
}

// 使用之前必须显式初始化
initialize()
println(myValue) // 输出: "Hello, World!"

检查初始化

  • 可以使用 ::property.isInitialized 语法来检查属性是否已经初始化。
    if (::myValue.isInitialized) {
      println(myValue)
    } else {
      println("myValue is not initialized")
    }
    

3. 两者对比

特性 by lazy lateinit
适用类型 val(只读属性) var(可变属性)
初始化时机 第一次访问时 必须手动初始化
线程安全 默认线程安全(可选择不同的线程安全模式) 非线程安全
Nullability 支持不可空类型 支持不可空类型(不能用于原始类型)
属性检查 不需要显式检查 可以通过 ::property.isInitialized 检查
自定义 getter/setter 不支持 不支持
使用场景 用于只读且惰性初始化的属性 用于需要在构造函数之外初始化的可变属性

示例场景

by lazy 适用场景:

  • 需要惰性初始化不可变的属性。
  • 需要线程安全的初始化或者只在单线程中操作。

    lateinit 适用场景:

    • 需要在构造方法之后初始化的可变属性。
  • 需要在某个特定操作时才对属性进行赋值。

总结来说,选择使用 by lazy 还是 lateinit 要依据属性的特性和具体的使用场景。by lazy 更适合不可变的延迟初始化场合,而 lateinit 则适用于在构造方法之后需要手动初始化的可变属性。


欢迎关注我的公众号AntDream查看更多精彩文章!

目录
相关文章
|
4月前
|
SQL 数据库
SQL面试50题------(初始化工作、建立表格)
这篇文章提供了SQL面试中可能会遇到的50道题目的建表和初始化数据的SQL脚本,包括学生、教师、课程和成绩表的创建及数据插入示例。
SQL面试50题------(初始化工作、建立表格)
|
4月前
Android.mk(makefile)中几个符号的区别:=、 :=、 ?=、 +=
本文解释了在Android.mk文件中使用的几种赋值符号的区别,包括`=`(基本赋值)、`:=`(覆盖赋值)、`?=`(条件赋值,仅在变量未赋值时操作)、`+=`(追加赋值),并通过实验演示了这些符号的具体行为和效果。
198 1
|
3月前
|
Android开发 Kotlin
Android经典面试题之Kotlin的==和===有什么区别?
本文介绍了 Kotlin 中 `==` 和 `===` 操作符的区别:`==` 用于比较值是否相等,而 `===` 用于检查对象身份。对于基本类型,两者行为相似;对于对象引用,`==` 比较值相等性,`===` 检查引用是否指向同一实例。此外,还列举了其他常用比较操作符及其应用场景。
193 93
|
2月前
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
26 1
|
2月前
|
Android开发 Kotlin
Android面试题之Kotlin中如何实现串行和并行任务?
本文介绍了 Kotlin 中 `async` 和 `await` 在并发编程中的应用,包括并行与串行任务的处理方法。并通过示例代码展示了如何启动并收集异步任务的结果。
29 0
|
2月前
|
Java 调度 Android开发
Android面试题之Kotlin中async 和 await实现并发的原理和面试总结
本文首发于公众号“AntDream”,详细解析了Kotlin协程中`async`与`await`的原理及其非阻塞特性,并提供了相关面试题及答案。协程作为轻量级线程,由Kotlin运行时库管理,`async`用于启动协程并返回`Deferred`对象,`await`则用于等待该对象完成并获取结果。文章还探讨了协程与传统线程的区别,并展示了如何取消协程任务及正确释放资源。
32 0
|
4月前
|
编解码 网络协议 开发工具
Android平台如何实现多路低延迟RTSP|RTMP播放?
本文档详细介绍了大牛直播SDK在Android平台上实现RTSP与RTMP流媒体播放及录像功能的技术细节。早在2015年,SDK的第一版就已经支持了多实例播放,并且通过简单的实例封装就能轻松实现。文档中提供了代码示例,展示了如何开启播放、停止播放以及开始和停止录像等功能。此外,SDK还提供了丰富的配置选项,例如设置录像目录、文件大小限制、转码选项等。总结部分列出了该SDK的关键特性,包括但不限于高稳定性和低延迟的播放能力、多实例支持、事件回调、硬解码支持、网络状态监控以及复杂的网络环境处理等。这些功能使得SDK能够应对各种应用场景,特别是在对延迟和稳定性有极高要求的情况下表现优异。
|
4月前
|
编解码 网络协议 vr&ar
Android平台下VR头显如何低延迟播放4K以上超高分辨率RTSP|RTMP流
这段内容讲述了VR头显中实现高分辨率视频播放的技术背景与实现方法,并强调了其重要性。高分辨率对于提升VR体验至关重要,它能提供更清晰的画面、增强沉浸感、补偿透镜放大效应,并维持宽广视场角下的图像质量。文中提到的大牛直播SDK具备极低的延迟(200-400ms),支持多种协议与格式,并具有丰富的功能特性,如多实例播放、事件回调、视频及音频格式支持等。此外,提供了基于Unity的播放器示例代码,展示了如何配置播放参数并开始播放。最后,作者指出此类技术在远程控制、虚拟仿真等应用场景中的重要意义。
|
5月前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin中常见作用域函数
**Kotlin作用域函数概览**: `let`, `run`, `with`, `apply`, `also`. `let`安全调用并返回结果; `run`在上下文中执行代码并返回结果; `with`执行代码块,返回结果; `apply`配置对象后返回自身; `also`附加操作后返回自身
62 8
|
5月前
|
Android开发 开发者
Android经典面试题之SurfaceView和TextureView有什么区别?
分享了`SurfaceView`和`TextureView`在Android中的角色。`SurfaceView`适于视频/游戏,独立窗口低延迟,但变换受限;`TextureView`支持复杂变换,视图层级中渲染,适合动画/视频特效,但性能略低。两者在性能、变换、使用和层级上有差异,开发者需按需选择。
89 1