ProgrammationDéveloppeur Android

Qu'est-ce que 'lateinit' et 'lazy' en Kotlin ? Expliquez les différences, les nuances d'utilisation, les limitations et donnez les exemples de code correspondants.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

En Kotlin, il existe deux approches différentes pour l'initialisation tardive des propriétés : lateinit et lazy.

lateinit — un modificateur appliqué aux variables (var) qui seront initialisées plus tard, généralement via DI ou dans un bloc d'initialisation. Convient uniquement aux variables non statiques de types NON nullable. L'accès avant l'initialisation lance une exception UninitializedPropertyAccessException.

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

lazy — un délégué spécial appliqué aux propriétés val (uniquement en lecture). L'expression d'initialisation est évaluée lors de la première utilisation de la variable. Sûr pour un accès multithreading par défaut.

val config: Config by lazy { loadConfigFromFile() }
  • lateinit ne fonctionne pas avec des types primitifs et val.
  • lazy ne permet pas la réinitialisation.
  • lateinit — pour les variables qui seront certainement assignées plus tard (par exemple, via un framework DI ou dans un fragment du cycle de vie Android).
  • lazy — pour les calculs paresseux, lorsque la valeur est coûteuse à calculer et peut ne pas être demandée.

Question piège

Peut-on utiliser lateinit pour des propriétés de type Int ?

Réponse : Non. lateinit ne fonctionne qu'avec des types objet NON nullable. Pas pour les primitifs et les types nullable - c'est impossible. Tenter de déclarer lateinit var a: Int entraînera une erreur de compilation.

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet


Histoire

Dans un projet éducatif, ils ont déclaré une variable de configuration comme lateinit var config: Config?, mais le compilateur n'a pas permis de le faire — ils ont gagné du temps, mais ont dû comprendre pourquoi cela ne fonctionnait pas comme prévu.


Histoire

Dans une application Android, ils ont oublié de vérifier l'initialisation de la propriété lateinit avant l'appel. Cela a conduit à un crash de l'application en production — le designer a tenté d'accéder à la propriété avant onCreateView. Des vérifications supplémentaires ont aidé.


Histoire

Lors de l'utilisation du multithreading, un développeur a utilisé by lazy pour initialiser un objet consommant des ressources sans passer de paramètre, pensant que le délégué par défaut n'était pas thread-safe. Au final, des problèmes de condition de course sont apparus dans la version. Ils ont résolu cela en passant le paramètre approprié pour lazy : by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { ... }.