Kotlin lazy特性

March 18, 2018

一、用法

Koltin的lazy懒加载主要有以下两种用法,根据具体实现看来只有方法二是懒加载的。

用法一:

1
val strLazyOf by lazyOf("LazyString")

用法二:

1
val strLazy by lazy { "LazyString" }

二、Lazy接口

SynchronizedLazyImplInitializedLazyImpl均实现Lazy接口

1
2
3
4
5
6
7
8
public interface Lazy<out T> {
    // 从当前懒加载实例中获取需加载值
    // 一旦值被初始化,该值在懒加载实例剩余生命周期都不应被修改
    public val value: T

    // 懒加载实例被初始化后此方法返回true,否则返回false
    public fun isInitialized(): Boolean
}

三、lazyOf源码

3.1 lazyOf

从实参value构造InitializedLazyImpl实例

1
public fun <T> lazyOf(value: T): Lazy<T> = InitializedLazyImpl(value)

3.2 InitializedLazyImpl

没有任何关于懒加载的逻辑

1
2
3
4
5
6
private class InitializedLazyImpl<out T>(override val value: T) : Lazy<T>, Serializable {

    override fun isInitialized(): Boolean = true

    override fun toString(): String = value.toString()
}

四、lazy {}源码

4.1 lazy

lazy线程安全,不需要在外层包加同步代码。

1
2
@kotlin.jvm.JvmVersion
public fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)

4.2 SynchronizedLazyImpl

单例UNINITIALIZED_VALUE用于表示值未初始化

1
private object UNINITIALIZED_VALUE

实现Lazy<T>Serializable两个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@JvmVersion
private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
    // 指定的初始值
    private var initializer: (() -> T)? = initializer

    // 值默认没有初始化,为UNINITIALIZED_VALUE,用Volatile关键字修饰
    @Volatile private var _value: Any? = UNINITIALIZED_VALUE

    // 如果不传入锁对象,默认把当前实例作为上锁对象
    private val lock = lock ?: this
    
    // 重写父类值value的行为
    override val value: T
        get() {
            // 值已被初始化就返回该值,并进行类型转换
            val _v1 = _value
            if (_v1 !== UNINITIALIZED_VALUE) {
                @Suppress("UNCHECKED_CAST")
                return _v1 as T
            }
            
            // 值没有经过初始化,先上同步锁
            return synchronized(lock) {
                val _v2 = _value
                // 双重校检,第一次是上方的检验
                // 下面是第二次校验
                if (_v2 !== UNINITIALIZED_VALUE) {
                    // aka: return value;
                    @Suppress("UNCHECKED_CAST") (_v2 as T)
                }
                else {
                    // 从initializer实例中获取输入值
                    val typedValue = initializer!!()
                    // 把值赋值给_value,_value保存在SynchronizedLazyImpl
                    _value = typedValue
                    // 使用过的initializer实例置null并回收
                    initializer = null
                    // aka: return typedValue;
                    typedValue
                }
            }
        }
    
    // 默认为false,经过初始化后变为true
    override fun isInitialized(): Boolean = _value !== UNINITIALIZED_VALUE

    override fun toString(): String = if (isInitialized()) value.toString() else "Lazy value not initialized yet."

    private fun writeReplace(): Any = InitializedLazyImpl(value)
}