
Types nullables : le `?`
Apprenez à déclarer des variables qui peuvent contenir `null` en Kotlin en utilisant le suffixe `?` sur le type. La base de la Null Safety expliquée.
La distinction fondamentale : nullable vs non-nullable
La pierre angulaire de la sécurité nulle (Null Safety) en Kotlin réside dans la distinction explicite faite par le système de types entre les références qui peuvent contenir `null` (nullables) et celles qui ne le peuvent pas (non-nullables). Cette distinction est au coeur de la prévention des `NullPointerException` (NPE).
Comme mentionné précédemment, par défaut en Kotlin, toutes les variables sont non-nullables. Cela signifie que le compilateur garantit qu'une variable déclarée sans indication spécifique ne contiendra jamais la valeur `null`. Essayer d'assigner `null` à une telle variable provoquera une erreur de compilation immédiate.
fun main() {
var name: String = "CertiQuizz" // Type non-nullable (String)
// name = null // Erreur de compilation: Null can not be a value of a non-null type String
val length: Int = 10 // Type non-nullable (Int)
// val anotherLength: Int = null // Erreur de compilation
println("Nom: $name")
}Cette règle par défaut élimine déjà une grande partie des risques de NPE, car le compilateur vous empêche activement d'introduire `null` là où ce n'est pas explicitement autorisé.
Déclarer l'intention : le suffixe `?`
Mais que faire lorsque vous avez besoin de représenter l'absence de valeur ? Par exemple, une propriété d'un objet qui est optionnelle, ou le résultat d'une fonction qui peut ne rien trouver. C'est là qu'intervient la syntaxe des types nullables.
Pour déclarer qu'une variable peut légitimement contenir soit une valeur de son type, soit `null`, vous devez ajouter un point d'interrogation (`?`) juste après le nom du type lors de la déclaration. Ce `?` transforme un type non-nullable en sa contrepartie nullable.
fun main() {
// Déclaration de variables nullables avec ?
var middleName: String? = "Robert" // Peut contenir une String ou null
var errorCode: Int? = null // Peut contenir un Int ou null
var description: String? = null // Initialisée à null
println("Prénom du milieu (initial): $middleName") // Affiche Robert
// Assignation de null à une variable nullable : OK
middleName = null
println("Prénom du milieu (après): $middleName") // Affiche null
errorCode = 404
println("Code d'erreur: $errorCode") // Affiche 404
errorCode = null
println("Code d'erreur (reset): $errorCode") // Affiche null
}En ajoutant le `?`, vous signalez explicitement au compilateur et aux autres développeurs que cette variable peut être `null` à un moment donné. Le type `String` est différent du type `String?`, `Int` est différent de `Int?`, etc.
La conséquence : le compilateur exige des vérifications
Le véritable pouvoir de cette distinction apparaît lorsque vous essayez d'utiliser une variable nullable. Le compilateur Kotlin, sachant que la variable pourrait être `null`, vous interdit d'accéder directement à ses propriétés ou méthodes sans avoir préalablement vérifié qu'elle n'est pas nulle. C'est cette vérification imposée qui prévient les NPE.
fun main() {
var maybeName: String? = "Alice"
maybeName = null // Elle peut devenir null
// Tentative d'accès direct à une propriété sur un type nullable
// println(maybeName.length) // Erreur de compilation!
// Message d'erreur typique: "Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String?"
var maybeNumber: Int? = 10
// println(maybeNumber.toString()) // Erreur de compilation également!
}L'erreur de compilation vous force à gérer le cas `null`. Vous ne pouvez plus simplement ignorer la possibilité qu'une référence soit nulle. Le compilateur devient votre filet de sécurité, vous empêchant d'écrire du code qui pourrait potentiellement crasher avec une NPE.
Cette contrainte imposée par le compilateur est la base de la Null Safety en Kotlin. Au lieu de compter sur la discipline du développeur pour ajouter des `if (variable != null)`, le compilateur exige une gestion explicite des types nullables. Les sections suivantes présenteront les différentes manières élégantes et sûres proposées par Kotlin pour effectuer ces vérifications et manipuler les valeurs nullables.
Récapitulatif : le rôle du `?`
Le point d'interrogation `?` ajouté à un type en Kotlin a un rôle précis et fondamental :
- Il déclare une variable comme étant nullable, signifiant qu'elle peut contenir une valeur de ce type ou `null`.
- Il oblige le compilateur à appliquer des règles strictes : tout accès à un membre (propriété ou méthode) de cette variable nullable nécessitera une vérification de nullité préalable.
C'est le premier pas vers l'éradication des `NullPointerException`, en intégrant la notion de nullabilité directement dans le contrat défini par le type de la variable.