Kotlin之lateinit关键字与lazy
前⾔
lateinit是许多刚进⼊学习kotlin常常会掉⼊的坑之⼀。很多⼈为了保证java原有的语法,在定义变量和对象的过程中,会使⽤如下的定义⽅式。
class Demo{
private var value: String
fun printValue(){
println(value)
}
}
这个时候,编译器就会提⽰错误
Error:(2, 5) Kotlin: Property must be initialized or be abstract
然后有很多⼩伙伴解决问题,会使⽤提⽰符快捷键按钮⾃动修复这个问题,结果发现在定义变量的位置多了⼀个lateinit关键字
private lateinit var value: String
编译器的问题就这样躲避过去了,可是运⾏的过程,还是发⽣了异常问题。
原理
lateinit修饰属性的时候,实际上就是表⽰,这个属性初始化的时机和⽅式,由开发者⾃⼰决定。⽽编译器在编译kotlin语⾔的过程中,会将lateinit修饰属性的所有调⽤位置都做⼀个⾮空的检查判断,然后抛出异常。
// 字节码等价代码
fun printValue(){
val tempValue =this.value
if(tempValue ==null){
throw UninitializedPropertyAccessException("lateinit property value has not been initialized")
}
println(tempValue)
}
你定义value属性的值确实为null,但由于给定value的类型为String类型,⽽kotlin当中String类型是不允许容纳null,kotlin为了保证“绝对的空安全性”,所以只能抛出异常。
对于 Kotlin 新⼿来说,应该抛开 Java 式的写法,牢记类属性的三种初始化⽅式:
主构造函数内定义属性,使⽤传⼊的参数初始化属性;
类体内定义属性,同时初始化;
kotlin 高阶函数类体内定义属性,init 块⾥初始化。
其他的初始化⽅式,慎⽤。
拓展
既然说到lateinit,那可以提⼀下kotlin中另⼀个常⽤的lazy。lazy并不是kotlin中的关键字,⽽是⼀个顶层函数,点击lazy跳转,可以看到lazy内部实现是通过⾼阶函数的⽅式。
tip:这⾥提到的顶层函数 和 ⾼阶函数 就不做拓展了,想要了解的可以通过资料⾃⾏了解。
val b by lazy{
// ...
}
// LazyJVM.kt
public actual fun<T>lazy(initializer:()-> T): Lazy<T>=SynchronizedLazyImpl(initializer)
先说⼀下lazy的作⽤,顾名思义是懒加载的意思。懒加载这个词,估计很多开发者都不会陌⽣,我第⼀次听到懒加载是在viewpage + fragment的使⽤当中,通过懒加载的⽅式来减少加载数据时产⽣的内存消耗。⽽kotlin中的lazy,则是当b这个这个属性第⼀次被使⽤的时候,就会去初始化b这个对象,lazy后⾯跟的时⼀个lambda表达式,最后⼀⾏作为返回对象赋值给b。
lazy 和 lateinit
1. lateinit 表⽰对全局变量进⾏延迟初始化,这样就不⽤⼀开始的时候将他赋值为null了。
2. lazy 表⽰当调⽤该属性时,会执⾏该lazy内部的getValue()函数,⽽getValue()⽅法⼜会调⽤到lazy函数传⼊的lambda表达式,这样
表达式的代码就可以得到执⾏。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论