两者都是 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$delegate
的 getValue()
方法
这个 getValue() 方法就是 Lazy 接口中的 value 属性,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 public interface Lazy <out T > { public val value: T 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 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 并返回