Kotlin中的 lateinit 和 by lazy

简介: Kotlin中的 lateinit 和 by lazy

延迟初始化

Koltin中属性在声明的同时也要求要被初始化,否则会报错。例如以下代码:

private var name0: String // 报错
private var name1: String = "xiaoming" // 不报错
private var name2: String? = null // 不报错

可是有的时候,我并不想声明一个类型可空的对象,而且我也没办法在对象一声明的时候就为它初始化,那么这时就需要用到Kotlin提供的延迟初始化

Kotlin中有两种延迟初始化的方式,分别是lateinit varby lazy

lateinit var

private lateinit var name: String

lateinit var只能用来修饰类属性,不能用来修饰局部变量,并且只能用来修饰对象,不能用来修饰基本类型(因为基本类型的属性在类加载后的准备阶段都会被初始化为默认值)。

lateinit var的作用也比较简单,就是让编译期在检查时不要因为属性变量未被初始化而报错。

Kotlin相信当开发者显式使用lateinit var 关键字的时候,他一定也会在后面某个合理的时机将该属性对象初始化的(然而,谁知道呢,也许他用完才想起还没初始化,那么你就会遇到UninitializedPropertyAccessException)。

by lazy

by lazy本身是一种属性委托。属性委托的关键字是byby关键字在kotlin中表达的委托的概念,by lazy只是会在使用到的时候进行初始化(类似懒汉式的单例),使用代理的方式调用get/set方法,所以var 不能声明by lazy修饰的属性。

by lazy 的写法如下:

// 用于属性延迟初始化
val name: Int by lazy { 1 } 
// 用于局部变量延迟初始化
public fun foo() {    
val bar by lazy { "hello" }    
println(bar)
}

by lazy要求属性声明为val,即不可变变量,在java中相当于被final修饰。

这意味着该变量一旦初始化后就不允许再被修改值了(基本类型是值不能被修改,对象类型是引用不能被修改)。{}内的操作就是返回唯一一次初始化的结果。

by lazy可以使用于类属性或者局部变量。

使用场景

虽然两者都可以推迟属性初始化的时间,但应用场景是略有不同的。

lateinit var只是让编译期忽略对属性未初始化的检查,后续在哪里以及何时初始化还需要开发者自己决定。

by lazy真正做到了声明的同时也指定了延迟初始化时的行为,在属性被第一次被使用的时候能自动初始化,但这些功能是要为此付出一丢丢代价的。


相关文章
|
5月前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
182 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
|
Java Kotlin
Kotlin 中初始化块、初始化的顺序、lateinit延迟初始化详解
Kotlin 中初始化块、初始化的顺序、lateinit延迟初始化详解
117 0
|
安全 Java 编译器
Kotlin | 关于 Lazy ,你应该了解的这些事
本文主要分享 Kotlin Lazy 相关,希望看完本篇,可以帮助到你更好的理解与使用。
432 0
Kotlin | 关于 Lazy ,你应该了解的这些事
|
Java Kotlin
能说一说 Kotlin 中 lateinit 和 lazy 的区别吗?
能说一说 Kotlin 中 lateinit 和 lazy 的区别吗?
|
Java 编译器 开发者
【Kotlin】变量简介 ( 可空类型 | lateinit | 初始化判定 | 非空类型 | !! 与 ? 修饰符 | ?= ?. ?: 运算符 | 抽象属性变量)(一)
【Kotlin】变量简介 ( 可空类型 | lateinit | 初始化判定 | 非空类型 | !! 与 ? 修饰符 | ?= ?. ?: 运算符 | 抽象属性变量)(一)
397 0
【Kotlin】变量简介 ( 可空类型 | lateinit | 初始化判定 | 非空类型 | !! 与 ? 修饰符 | ?= ?. ?: 运算符 | 抽象属性变量)(一)
|
存储 Kotlin
【Kotlin】属性 与 幕后字段 ( 属性声明 | 属性初始化器 | 属性访问器 | field 属性幕后字段 | lateinit 延迟初始化属性 )
【Kotlin】属性 与 幕后字段 ( 属性声明 | 属性初始化器 | 属性访问器 | field 属性幕后字段 | lateinit 延迟初始化属性 )
229 0
【Kotlin】属性 与 幕后字段 ( 属性声明 | 属性初始化器 | 属性访问器 | field 属性幕后字段 | lateinit 延迟初始化属性 )
|
Java 测试技术 Kotlin
Kotlin:关键字之lateinit
Kotlin:关键字之lateinit
492 0
Kotlin:关键字之lateinit
|
存储 安全 Java
从源码角度分析 Kotlin by lazy 的实现
从源码角度分析 Kotlin by lazy 的实现
356 0
|
Java Kotlin
【Kotlin】变量简介 ( 可空类型 | lateinit | 初始化判定 | 非空类型 | !! 与 ? 修饰符 | ?= ?. ?: 运算符 | 抽象属性变量)(二)
【Kotlin】变量简介 ( 可空类型 | lateinit | 初始化判定 | 非空类型 | !! 与 ? 修饰符 | ?= ?. ?: 运算符 | 抽象属性变量)(二)
230 0
|
2月前
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
40 1