ProgrammierungAndroid Entwickler

Was sind 'lateinit' und 'lazy' in Kotlin? Erklären Sie die Unterschiede, Nutzungshinweise, Einschränkungen und geben Sie entsprechende Codebeispiele.

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

In Kotlin gibt es zwei verschiedene Ansätze zur späten Initialisierung von Eigenschaften: lateinit und lazy.

lateinit — ein Modifikator, der auf Variablen (var) angewendet wird, die später initialisiert werden, normalerweise durch DI oder im Initialisierungsblock. Geeignet nur für nicht-statische, nicht nullable-Variablen. Der Zugriff vor der Initialisierung wirft eine UninitializedPropertyAccessException-Ausnahme.

class MyClass { lateinit var data: String fun init() { data = "Hello!" } }

lazy — ein spezieller Delegate, der auf val-Eigenschaften (nur read-only) angewendet wird. Der Initialisierungs-Ausdruck wird beim ersten Zugriff auf die Variable berechnet. Standardmäßig sicher für den mehrstufigen Zugriff.

val config: Config by lazy { loadConfigFromFile() }
  • lateinit funktioniert nicht mit primitiven Typen und val.
  • lazy erlaubt keine Wiederinitialisierung.
  • lateinit ist für Variablen gedacht, die garantiert später zugewiesen werden (zum Beispiel über ein DI-Framework oder im Lebenszyklusfragment von Android).
  • lazy ist für faule Berechnungen gedacht, wenn der Wert teuer zu berechnen ist und möglicherweise nicht benötigt wird.

Fangfrage

Kann lateinit für Eigenschaften des Typs Int verwendet werden?

Antwort: Nein. lateinit funktioniert nur mit objekt-basierten, nicht nullable Typen. Für primitive und nullable Typen — nicht erlaubt. Der Versuch, lateinit var a: Int zu deklarieren, führt zu einem Kompilierungsfehler.

Beispiele aus der Praxis für Fehler aufgrund fehlenden Wissens über die Feinheiten des Themas


Geschichte

In einem Bildungsprojekt wurde die Konfigurationsvariable als lateinit var config: Config? deklariert, aber der Compiler erlaubte dies nicht — sie haben Zeit gespart, mussten aber herausfinden, warum es nicht wie erwartet funktioniert.


Geschichte

In einer Android-Anwendung wurde vergessen, vor dem Aufruf die Initialisierung des lateinit-Eigenschaft zu überprüfen. Dies führte zum Absturz der Anwendung in der Produktionsumgebung — der Designer versuchte, auf die Eigenschaft vor onCreateView zuzugreifen. Zusätzliche Überprüfungen haben geholfen.


Geschichte

Bei der Verwendung von Mehrfachverarbeitung hat der Entwickler by lazy zur Initialisierung eines ressourcenintensiven Objekts ohne Parameterübergabe verwendet, da er annahm, dass der Delegate standardmäßig nicht thread-sicher ist. In der Folge traten im Release Probleme mit Race Conditions auf. Dies wurde durch die Übergabe des entsprechenden Parameters für lazy gelöst: by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ... }.