Kotlin by lazy 延迟初始化

2,093 阅读1分钟

使用方法

val xxx by lazy {

}

原理分析

  • by 属性代理
    kotlin中的属性代理, 代理对象提供 getValuesetValue 方法来完成对属性的访问和修改。

  • lazy
    lazy 是一个方法, 它有一个 lambda 类型的参数, 并且返回一个 Lazy 类型的属性代理对象。

    // lazy 方法
    fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)
    
  • Lazy
    Lazy 是一个接口, 有一个 value 属性表示代理的属性。Lazy.kt 中对其进行了拓展, 添加了 getValue 的拓展方法, 直接返回 value 属性(符合 by 属性代理的要求)。同时由于只提供了getValue 方法因此定义的变量用 val 修饰。

    public interface Lazy<out T> {
        public val value: T
        public fun isInitialized(): Boolean
    }
    // 拓展了一个 getValue 的方法
    public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
    
  • SynchronizedLazyImpl
    lazy 方法返回的实际对象, 继承 Lazy, 在 value 属性的 get 方法中对获取进行 synchronized 同步, 保证多线程的情况系变量只被初始化一次。

    override val value: T
          get() {
              val _v1 = _value
    			// 已经初始化过了
              if (_v1 !== UNINITIALIZED_VALUE) {
                  return _v1 as T
              }
              // 加锁同步
              return synchronized(lock) {
                  val _v2 = _value
                  if (_v2 !== UNINITIALIZED_VALUE) {
                  } else {
                      val typedValue = initializer!!()
                      _value = typedValue
                      initializer = null
                      typedValue
                  }
              }
          }