Kotlin 中的懒加载 lazy

两者都是 Kotlin 中用来延迟加载类属性的方法

lateinit var 不能用来修饰基本类型,因为 Kotlin 中用来判断变量是否初始化是通过判断该变量是否为 null 来作为依据的,而基本类型在初始化的时候会默认赋值,所以 lateinit var 不能修饰基本类型

by lazy 是属性委托,会在调用该属性时再初始化该属性,之后将其进行保存,后续不再进行初始化而是直接返回其值/引用

通过个例子举例:

1
2
3
class Test {
private val name by lazy { "" }
}

通过反编译为 Java 代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public final class Test {
private final Lazy name$delegate;

private final String getName() {
Lazy var1 = this.name$delegate;
Object var3 = null;
boolean var4 = false;
return (String)var1.getValue();
}

public Test() {
this.name$delegate = LazyKt.lazy((Function0)null.INSTANCE);
}
}
1
2
3
4
LazyJVM.kt

public actual fun <T> lazy(initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer)

可见该类在构造方法中会将 name$delegate 赋值为 LazyKt.lazy((Function0)null.INSTANCE),LazyKt.lazy() 的入参方法是一个 lambda 表达式,用来获取属性的值,返回值是一个 Lazy 对象

在调用 getName() 时候会调用 name$delegategetValue() 方法

这个 getValue() 方法就是 Lazy 接口中的 value 属性,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface Lazy<out T> {
/**
* Gets the lazily initialized value of the current Lazy instance.
* Once the value was initialized it must not change during the rest of lifetime of this Lazy instance.
*/
public val value: T

/**
* Returns `true` if a value for this Lazy instance has been already initialized, and `false` otherwise.
* Once this function has returned `true` it stays `true` for the rest of lifetime of this Lazy instance.
*/
public fun isInitialized(): Boolean
}

Lazy<T> 其中一个实现类为 SynchronizedLazyImpl

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
private class SynchronizedLazyImpl<out T>(initializer: () -> T, lock: Any? = null) : Lazy<T>, Serializable {
private var initializer: (() -> T)? = initializer
@Volatile private var _value: Any? = UNINITIALIZED_VALUE
// final field is required to enable safe publication of constructed instance
private val lock = lock ?: this

override val value: T
get() {
val _v1 = _value
if (_v1 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST")
return _v1 as T
}

returnsynchronized(lock){
val _v2 = _value
if (_v2 !== UNINITIALIZED_VALUE) {
@Suppress("UNCHECKED_CAST") (_v2 as T)
} else {
val typedValue = initializer!!()
_value = typedValue
initializer = null
typedValue
}
}
}

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)
}

可见 value 的值获取会先和 UNINITIALIZED_VALUE 比较

如果不同,则说明已经初始化过了,则直接强转其类型并返回

否则,则通过 initializer() 方法初始化其值,并赋值给 _value 并返回

作者

PPTing

发布于

2022-04-09

更新于

2022-04-09

许可协议

评论