lateinit en Kotlin : comment vérifier si une variable est initialisée

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : pourquoi lateinit est à la fois pratique et dangereux

\n\n

Si vous écrivez en Kotlin depuis au moins quelques semaines, vous avez sûrement déjà rencontré cette situation : vous devez déclarer une variable qui ne sera certainement pas nulle, mais l'initialiser immédiatement est impossible. Par exemple, lorsque les données proviennent d'une API externe, d'une saisie utilisateur ou après le chargement d'une configuration. En Java, nous aurions simplement écrit String name = null; et oublié. Mais Kotlin est un langage avec une null safety stricte, et on ne peut pas simplement assigner null à une variable.

\n\n

C'est là qu'intervient le modificateur lateinit. Il permet de déclarer une variable non nulle sans initialisation immédiate, en la reportant à plus tard. Cela semble idéal, n'est-ce pas ? Mais il y a un hic : si vous essayez d'accéder à une telle variable avant qu'elle n'ait reçu une valeur, Kotlin lèvera une UninitializedPropertyAccessException. Et votre application plantera.

\n\n

C'est précisément ici qu'apparaît la question populaire de Stack Overflow (avec des milliers de vues) : « How to check if a lateinit variable has been initialized? ». Dans cet article, nous ne nous contenterons pas de donner la réponse — nous analyserons le mécanisme de fonctionnement de lateinit, montrerons comment vérifier en toute sécurité l'état de la variable, et expliquerons quand lateinit est le bon choix et quand il est préférable d'utiliser d'autres approches.

\n\n

Qu'est-ce que lateinit et pourquoi en a-t-on besoin ?

\n\n

Le modificateur lateinit est une promesse faite au compilateur : « Je sais que cette variable est actuellement vide, mais je garantis que je la remplirai avant la première utilisation ». Kotlin vous fait confiance et n'exige pas d'assigner une valeur directement au point de déclaration.

\n\n

Les principales caractéristiques de lateinit :

\n
    \n
  • Ne peut être appliqué qu'à var (propriétés mutables), pas à val.
  • \n
  • Fonctionne uniquement avec les types références (classes, chaînes, collections). Les primitives (Int, Double, etc.) — non.
  • \n
  • Ne peut pas être utilisé pour les types nullable (avec ?).
  • \n
  • Ne prend pas en charge les getters et setters personnalisés.
  • \n
\n\n

Un exemple classique est le développement Android, où les objets sont souvent initialisés dans onCreate() ou onViewCreated() :

\n\n
class MainActivity : AppCompatActivity() {\n    lateinit var userAdapter: UserAdapter\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        // Ici, nous devons initialiser userAdapter\n        userAdapter = UserAdapter(emptyList())\n    }\n\n    fun updateAdapter(newList: List<User>) {\n        // Sécurisé, car nous savons que onCreate a déjà été exécuté\n        userAdapter.updateData(newList)\n    }\n}\n
\n\n

Mais que se passe-t-il si quelqu'un appelle updateAdapter() avant onCreate() ? Exactement — un crash. Et c'est là que la vérification d'initialisation nous est utile.

\n\n

Comment vérifier si une variable lateinit est initialisée ?

\n\n

Kotlin fournit une propriété intégrée isInitialized, accessible via la réflexion pour toute propriété lateinit. La syntaxe est simple : ::propertyName.isInitialized. Notez le double deux-points — c'est l'opérateur de référence de propriété.

\n\n

Voici un exemple de base :

\n\n
class DataManager {\n    lateinit var config: Config\n\n    fun loadConfig() {\n        // Simulation du chargement de la configuration\n        config = Config("production", 8080)\n    }\n\n    fun printConfig() {\n        if (::config.isInitialized) {\n            println("Configuration : ${config.mode}, port : ${config.port}")\n        } else {\n            println("La configuration n'est pas encore chargée !")\n        }\n    }\n}\n\nfun main() {\n    val manager = DataManager()\n    manager.printConfig() // Affiche : La configuration n'est pas encore chargée !\n    manager.loadConfig()\n    manager.printConfig() // Affiche : Configuration : production, port :                

Blogs

Book Recommendations