En Kotlin existen dos enfoques diferentes para la inicialización tardía de propiedades: lateinit y lazy.
lateinit — un modificador aplicado a variables (var) que serán inicializadas más tarde, generalmente a través de DI o en un bloque de inicialización. Solo es adecuado para variables no estáticas de tipos NO nullable. Acceder antes de la inicialización provoca la excepción UninitializedPropertyAccessException.
class MyClass { lateinit var data: String fun init() { data = "¡Hola!" } }
lazy — un delegado especial aplicado a propiedades val (solo de solo lectura). La expresión inicializadora se evalúa en la primera referencia a la variable. Por defecto, es seguro para el acceso multihilo.
val config: Config by lazy { loadConfigFromFile() }
lateinit no funciona con tipos primitivos y val.lazy no permite la reinicialización.lateinit es para variables que seguramente serán asignadas más tarde (por ejemplo, a través de un marco DI o en un fragmento del ciclo de vida de Android).lazy es para cálculos perezosos, cuando el valor es costoso de calcular y puede que no se necesite.¿Se puede usar
lateinitpara propiedades de tipo Int?
Respuesta: No. lateinit solo funciona con tipos no nullable de objetos. No se permite para primitivos y tipos nullable. Intentar declarar lateinit var a: Int resultará en un error de compilación.
Historia
En un proyecto educativo, declararon una variable de configuración como lateinit var config: Config?, pero el compilador no permitió hacerlo; ahorramos tiempo, pero tuvimos que investigar por qué no funcionaba como esperábamos.
Historia
En una aplicación de Android, olvidaron verificar la inicialización de la propiedad lateinit antes de la llamada. Esto llevó a un fallo en la aplicación en producción: el diseñador intentó acceder a la propiedad antes de onCreateView. Se ayudó con verificaciones adicionales.
Historia
Al usar multithreading, el desarrollador aplicó by lazy para inicializar un objeto costoso sin pasar el parámetro, asumiendo que el delegado por defecto no era seguro para hilos. Como resultado, aparecieron problemas de condición de carrera en la versión final. Se resolvió pasando el parámetro correspondiente para lazy: by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ... }.