Inicialización de propiedades: lateinit vs lazy

video[Tutorial Inicialización de propiedades lateinit vs lazy

Normalmente, aquellas variables que no se declaren como nulas, se deben inicializar en el constructor. Sin embargo, frecuentemente esto no es lo más adecuado. En caso de que no queramos inicializar una propiedad en el constructor, disponemos de dos alternativas, lateinit y lazy.
Mediante lateinit lo que conseguimos es una inicialización tardía, indicando al compilador que dicha inicialización se realizará más adelante en el código. Si intentamos acceder a alguna variable antes de su inicialización obtendremos un error del tipo Caused by: kotlin.UninitializedPropertyAccessException: lateinit property test has not been initialized.
 

lateinit var texto: String
fun doSomething() {
   texto = "Un valor"
   println("La longitud es "+texto.length)
   texto = "Otro valor"
} 
El modificador lateinit solo puede ser utilizado en variables mutables (var) declaradas en el cuerpo de una clase (no el en constructor primario), y solo cuando dicha variable no tiene un getter o setter personalizado.
Mediante lazy lo que conseguimos es una inicialización perezosa, con lo que una variable no será inicializada a no ser que sea utilizada en nuestro código. Será inicializada una única vez tras lo cual mantendrá el valor.
public class Ejemplo{
   val nombre: String by lazy { "Gonzalo Puga" }
} 
En este ejemplo, tanto las primeras llamadas a nombre como las subsecuentes, devolverán "Gonzalo Puga"
Una vez que sabemos qué hace cada una de estas funciones, ¿cuándo debemos utilizar cada una de ellas?
  • *   lazy solo se puede utilizar para variables inmutables val, mientras que lateinit solo se pueden aplicar a variables mutables var, ya que no se puede asegurar la inmutabilidad de dicha variable al no poder compilarse como final.
  • *   Una variable de tipo lateinit se podrá inicializar en cualquier parte del objeto donde sea visible. Si necesitamos que nuestra variable sea inicializada desde fuera, de un modo desconocido de antemano, deberemos utilizar lateinit.