Der Unterschied zwischen Kotlins lateinit und by faul

Eins, lateinit

1. Verwendung von lateinit

Da Kotlin strenge grammatikalische Anforderungen hat, müssen Variablen angeben, ob sie null sein können, aber in tatsächlichen Geschäftsszenarien muss diese Variable irgendwann initialisiert werden, und diese Variable darf nicht null sein.Wenn sie null ist, ist es logisch ein Problem. Zu diesem Zeitpunkt kann lateinit verwendet werden, um diese Variable zu ändern. Wenn diese Variable ohne Initialisierung verwendet wird, wird eine Ausnahme ausgelöst.

class LateInitExample {
    lateinit var value:String
}

fun main() {
    val example = LateInitExample()
    // 如果没有赋值就使用,直接抛出异常。
    example.value = "lateinit example"
    println("${example.value}")
}

2. Die spezifische Implementierung von lateinit

public class LateInitExample {

    private String value;

    public String getValue() {
        // 如果没有初始化过,就抛出异常
        if (value == null){
            throw new RuntimeException("lateinit property value has not been initialized");
        }
        return value;
    }

    public void setValue(String value) {
        // 这里要做非null检查
        this.value = value;
    }
}

Wir wissen, dass die Verwendung von kotlins Eigenschaften eigentlich das Aufrufen der get- und set-Methoden ist, und das Schlüsselwort lateinit führt tatsächlich einige Operationen mit den get- und set-Methoden aus.

Beachten Sie, dass lateinit keine primitiven Typen ändern kann.

Zwei, durch faul

By und faul sollten separat betrachtet werden, nicht als Ganzes.

by: Hierbei handelt es sich um das Delegationsattribut in der Delegation von Kotlin .

faul: eine Kotlin-Funktion

1. Eigentumsübertragung

Das einfache und weitverbreitete Verständnis ist, dass Get und Set dieser Variablen einer anderen Klasse zur Ausführung anvertraut werden.

Wenn es sich um eine var-Variable handelt, müssen zwei Methoden getValue und setValue vorhanden sein, und die val-Variable benötigt die setValue-Methode nicht.

// 委托的类
class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, 这里委托了 ${property.name} 属性"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$thisRef 的 ${property.name} 属性赋值为 $value")
    }
}

Achten Sie darauf, nicht mit den get- und set-Methoden von kotlin zu verwechseln!!!!

Die Syntax lautet: val/var <Eigenschaftsname>: <Typ> durch <Ausdruck>

Die Kotlin-Standardbibliothek bietet Factory-Methoden für mehrere nützliche Delegaten, und die Lazy-Eigenschaft Lazy ist eine davon.

https://www.runoob.com/kotlin/kotlin-delegated.html

2. Implementierung von faul

public actual fun <T> lazy(lock: Any?, initializer: () -> T): Lazy<T> = SynchronizedLazyImpl(initializer, lock)



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
            }

            return synchronized(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)
}

Wenn ich das sehe, bleibt meiner Meinung nach nur noch ein Zweifel für alle übrig: Warum gibt es keine getValue-Methode?Bedeutet das nicht, dass die Implementierung von by die getValue-Methode benötigt? Hier verwendet Kotlin Erweiterungsfunktionen, um dies zu tun.


// 这里返回value,就会执行实现类的override value get了。
public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value

3. Zusammenfassung

Im Wesentlichen spiegelt sich der Unterschied zwischen lateinit und by lazy im Speicher wider:

Die von lateinit geänderten Attribute werden im Speicher erstellt, aber es gibt keine Zuweisung

Das von faul modifizierte Attribut wird nur dann im Speicher erstellt, wenn es verwendet wird

Guess you like

Origin blog.csdn.net/m0_37707561/article/details/128662181