Nullable en Kotlin : comment travailler avec les valeurs null sans douleur ? Guide complet

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

Qu'y a-t-il derrière le point d'interrogation ? Plongeons dans nullable en Kotlin

\n\n

Avez-vous déjà écrit en Java et attrapé un NullPointerException au pire moment ? Si oui — vous savez à quel point c'est douloureux. Les développeurs de Kotlin ont résolu ce problème une fois pour toutes, en faisant de la null safety non pas une simple fonctionnalité, mais une philosophie du langage. Mais les débutants sont souvent effrayés par la question : "In Kotlin, what is the idiomatic way to deal with nullable values, referencing or converting them?" (c'est exactement ainsi que sonne la question la plus populaire sur Stack Overflow).

\n\n

Aujourd'hui, nous allons analyser toutes les idiomes de travail avec nullable : du simple ?. au rusé let et au magique !!. Et surtout — nous allons regarder sous le capot pour comprendre comment cela fonctionne au niveau du byte-code. C'est parti !

\n\n

Petit rappel : qu'est-ce que nullable ?

\n\n

En Kotlin, les types sont divisés en deux camps : nullable (peuvent être null) et non-nullable (ne le peuvent pas). Si vous écrivez var name: String = null — le compilateur générera une erreur. Par contre var name: String? = null — c'est ok. Le point d'interrogation est un marqueur qui dit : "Hé, compilateur, je sais qu'il peut y avoir du vide ici, ne t'énerve pas".

\n\n

Mais comment travailler avec cela ? Vérifier simplement avec if pour null — c'est ennuyeux et pas très kotlin-esque. Regardons les vrais outils.

\n\n

Le trio salvateur : ?, ?: et ?.

\n\n

Kotlin propose trois piliers sur lesquels repose tout le travail avec nullable. Souvenez-vous-en — ils vous feront gagner des heures de débogage.

\n\n

1. Safe call operator (?.)

\n\n

C'est l'invité le plus fréquent dans votre code. L'opérateur safe call permet d'appeler une méthode ou une propriété uniquement si l'objet n'est pas null. Si l'objet est null — l'opérateur retourne null, et aucune exception.

\n\n
val user: User? = null\nval name: String? = user?.name  // name = null, aucune erreur
\n\n

Sous le capot, cela se transforme en byte-code qui effectue une simple vérification de null et un appel conditionnel. Pas de magie, seulement de la sécurité.

\n\n

2. Elvis operator (?:)

\n\n

Elvis est votre ami quand vous devez substituer une valeur par défaut. Si la partie gauche n'est pas null — on la prend, sinon — celle de droite.

\n\n
val name: String? = null\nval displayName: String = name ?: "Invité"  // "Invité"
\n\n

Elvis peut aussi être utilisé pour une sortie anticipée d'une fonction :

\n\n
fun getUserName(user: User?): String {\n    val name = user?.name ?: return "Anonyme"\n    return name\n}
\n\n

3. Not-null assertion (!!)

\n\n

C'est l'opérateur rebelle. Il dit : "Je suis sûr que ce n'est pas null ici, et je suis prêt à mourir (dans le sens, lancer une NPE) si je me trompe". Utilisez-le avec précaution, seulement quand vous êtes sûr à 100%.

\n\n
val user: User? = getUserFromDatabase() // nous sommes sûrs qu'il existe\nval name: String = user!!.name
\n\n

Sous le capot, !! se compile en une simple vérification avec lancement de NullPointerException en cas de null. Rien de compliqué, mais dangereux.

\n\n

La manière idiomatique : let, run, apply et compagnie

\n\n

Passons maintenant à la partie la plus intéressante. La question sur Stack Overflow porte justement là-dessus : comment transformer idiomatiquement les valeurs nullable. La réponse — les fonctions d'extension de la bibliothèque standard.

\n\n

let — le roi des transformations nullable

\n\n

La fonction let exécute un bloc de code uniquement si l'objet n'est pas null. À l'intérieur du bloc, l'objet est accessible en tant que it (ou on peut le renommer).

\n\n
val user: User? = getUser()\nuser?.let { \n    println("Nom d'utilisateur : ${it.name}")\n    // Ici it — garanti non null\n}
\n\n

C'est la manière idiomatique d'effectuer une action uniquement pour une valeur non-null. Sans let, il faudrait écrire :

\n\n
if (user != null) {\n    println("Nom d'utilisateur : ${user.name}")\n}

Blogs

Book Recommendations