Kotlin-简约之美-进阶篇(六):延迟初始化lateinit var和by lazy

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

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

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

lateinit var

private lateinit var name: String
  1. lateinit var只能用来修饰类属性,不能用来修饰局部变量,并且只能用来修饰对象,不能用来修饰基本类型(因为基本类型的属性在类加载后的准备阶段都会被初始化为默认值)。
  2. lateinit var的作用也比较简单,就是让编译期在检查时不要因为属性变量未被初始化而报错。
  3. Kotlin相信当开发者显式使用lateinit var 关键字的时候,他一定也会在后面某个合理的时机将该属性对象初始化的

by lazy

by lazy本身是一种属性委托。属性委托的关键字是by。by lazy 的写法如下:

//用于属性延迟初始化
val name: Int by lazy { 1 }

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

by lazy具体是怎么实现的:生成一个该属性的附加属性:nameXXdelegate
在构造器中,将使用lazy(()->T)创建的Lazy实例对象赋值给nameXXdelegate;
当该属性被调用,即其getter方法被调用时返回nameXXdelegate.getVaule(),而nameXXdelegate.getVaule()方法的返回结果是对象nameXXdelegate内部的_value属性值,在getVaule()第一次被调用时会将_value进行初始化,往后都是直接将_value的值返回,从而实现属性值的唯一一次初始化。

lateinit var和by lazy使用区别?

虽然两者都可以推迟属性初始化的时间,但是lateinit var只是让编译期忽略对属性未初始化的检查,后续在哪里以及何时初始化还需要开发者自己决定。而by lazy真正做到了声明的同时也指定了延迟初始化时的行为,在属性被第一次被使用的时候能自动初始化。

推荐阅读更多精彩内容