In Kotlin zijn er twee verschillende benaderingen voor late initialisatie van eigenschappen: lateinit en lazy.
lateinit is een modifier die wordt toegepast op variabelen (var), die later geïnitialiseerd zullen worden, meestal via DI (dependency injection) of in een initialisatieblok. Geschikt alleen voor niet-statische variabelen van NIET nullable-typen. Toegang vóór initialisatie genereert een UninitializedPropertyAccessException.
class MyClass { lateinit var data: String fun init() { data = "Hello!" } }
lazy is een speciale delegate die wordt toegepast op val-eigenschappen (alleen read-only). De initialisatie-expressie wordt berekend bij de eerste toegang tot de variabele. Is standaard veilig voor multithreading.
val config: Config by lazy { loadConfigFromFile() }
lateinit werkt niet met primitieve types en val.lazy staat geen herinitialisatie toe.lateinit is voor variabelen die gegarandeerd later zullen worden toegewezen (bijvoorbeeld via een DI-framework of in een Android lifecycle fragment).lazy is voor luiere berekeningen, wanneer de waarde kostbaar is in berekeningen en mogelijk niet nodig is.Kan
lateinitgebruikt worden voor eigenschappen van het type Int?
Antwoord: Nee. lateinit werkt alleen met objectrijke NIET nullable-typen. Voor primitieve en nullable-typen kan dit niet. Proberen om lateinit var a: Int te declareren leidt tot een compileerfout.
Verhaal
In een educatief project werd de configuratievariabele gedeclareerd als lateinit var config: Config?, maar de compiler stond dit niet toe - tijd bespaard, maar we moesten uitzoeken waarom het niet werkte zoals verwacht.
Verhaal
In een Android-applicatie vergeten om te controleren op initialisatie van de lateinit-eigenschappen voordat deze werden aangeroepen. Dit leidde tot een crash van de applicatie in productie - de ontwerper probeerde toegang te krijgen tot de eigenschap vóór onCreateView. Extra controles hielpen.
Verhaal
Bij het gebruik van multithreading nam de ontwikkelaar by lazy voor de initialisatie van een resource-intensief object zonder de parameter door te geven, in de veronderstelling dat de delegate standaard niet thread-veilig is. Uiteindelijk deden zich raceconditionproblemen voor in de release. Dit werd opgelost door de juiste parameter voor lazy door te geven: by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ... }.