[Kotlin] La diferencia entre lateinit y lazy lazy initialization

preámbulo

En Kotlin, de hecho, hay dos formas de implementar la inicialización diferida: lateinit y lazy. Ambos le permiten inicializar variables cuando sea necesario, pero tienen algunas diferencias.

latín

1lateinit 关键字只能用于修饰可变的属性(var),不能用于不可变的属性(val)。

2 你可以在任何地方延迟初始化使用 lateinit,而不仅仅局限于顶层属性或对象属性。

3需要注意的是,对于使用 lateinit 延迟初始化的属性,在使用前必须显式赋值,否则会引发异常。

lateinit var name: String

// 使用前必须显式赋值
name = "John Doe"
println(name)

4延迟初始化的属性不能使用空安全操作符(?. 和 !!.),因为它们不能确定属性是否已经被正确初始化。

perezoso

1lazy 是一个函数,它接受一个 lambda 表达式作为参数,返回一个 Lazy<T> 实例。使用 by lazy 将该实例与属性关联起来。

2lazy 只能用于修饰不可变的属性(val),不能用于可变的属性(var)。

3lazy 的属性只会在首次访问时进行初始化,之后的访问将直接返回已经初始化的值。

4lazy 属性是线程安全的,因此在多线程环境下可以安全使用。

val randomNumber: Int by lazy {
    
    
    println("Initializing random number")
    (0..100).random()
}

// 首次访问时进行初始化
println(randomNumber)
// 直接返回已经初始化的值
println(randomNumber)

ejemplo

Veamos un ejemplo usando lateinit

class Person {
    
    
    lateinit var name: String
    
    fun initializeName() {
    
    
        name = "John Doe"
    }
    
    fun printName() {
    
    
        if (::name.isInitialized) {
    
    
            println(name)
        } else {
    
    
            println("Name is not initialized yet.")
        }
    }
}

val person = Person()
person.initializeName()
person.printName()

En el código anterior, definimos una clase de Persona y creamos un nombre de propiedad mutable inicializado perezosamente. En el método initializeName(), asignamos un valor al atributo de nombre. Luego, en el método printName(), verificamos si la propiedad del nombre se ha inicializado y, de ser así, imprimimos el nombre; de ​​lo contrario, imprimimos un mensaje sin inicializar.

A continuación, veamos un ejemplo usando perezoso:

val randomNumber: Int by lazy {
    
    
    println("Initializing random number")
    (0..100).random()
}

fun main() {
    
    
    println(randomNumber)
    println(randomNumber)
}

En el código anterior, definimos una propiedad inmutable randomNumber que usa la función diferida para la inicialización diferida. En la expresión lambda de la función perezosa, emitimos el mensaje de inicialización y generamos un número aleatorio. En la función main(), imprimimos la propiedad randomNumber dos veces.

Ejecutando el código anterior, la salida será:

Initializing random number
58
58

Como puede ver en la salida, la propiedad perezosa solo se inicializa la primera vez que se accede a ella. Cuando se accede por segunda vez, el valor inicializado se devuelve directamente sin ejecutar el bloque de código de inicialización.

En resumen, la diferencia entre lateinit y lazy es:

1lateinit需要在使用之前进行初始化,否则会抛出异常,而lazy在第一次访问时进行初始化,且不需要提前初始化。

2lateinit不能用于原生类型,只能用于可空类型;而lazy可以用于任何可空类型。

3lateinit只能在类内部声明,而lazy可以在任何作用域中声明。

4lateinit只能使用var关键字声明,lazy可以使用val或var关键字声明。

5lazy属性提供了内置的线程安全机制,确保只有一个线程能够进行初始化,而lateinit属性没有提供内置的线程安全机制,需要开发人员自己管理线程安全性。

6lateinit属性的错误在运行时捕获,lazy属性的错误在编译时捕获。

Guess you like

Origin blog.csdn.net/qq_43358469/article/details/131823334