Comment gérer correctement les exceptions en Kotlin?
sobes.tech IA
Réponse de l'IA
En Kotlin, la gestion des exceptions utilise la construction try...catch...finally. Vous pouvez appeler des fonctions annotées avec @Throws pour interagir avec du code Java.
fun readFile(path: String): String {
return try {
// Tentative d'exécuter un code potentiellement dangereux
java.io.File(path).readText()
} catch (e: java.io.IOException) {
// Gestion d'une exception spécifique
println("Erreur lors de la lecture du fichier : ${e.message}")
"" // Retourne une valeur par défaut en cas d'erreur
} finally {
// Bloc qui s'exécute toujours, indépendamment de l'exception
println("Lecture du fichier terminée")
}
}
Il est possible d'utiliser plusieurs blocs catch pour gérer différents types d'exceptions :
fun processData(data: String) {
try {
// Code pouvant lancer NumberFormatException ou NullPointerException
val number = data.toInt()
println("Nombre : $number")
} catch (e: NumberFormatException) {
println("Format de nombre invalide : ${e.message}")
} catch (e: NullPointerException) {
println("Données nulles reçues : ${e.message}")
}
}
Kotlin ne possède pas d'exceptions vérifiées comme en Java. Les fonctions peuvent déclarer qu'elles peuvent lancer des exceptions avec @Throws, mais ce n'est pas obligatoire en code Kotlin.
Pour les cas où une fonction peut réussir ou échouer, on utilise souvent des classes scellées (sealed classes) ou le type Result (dans des versions expérimentales de Kotlin) au lieu des exceptions, notamment dans le code asynchrone.
Exemple avec une classe scellée :
sealed class Result<out T>
data class Success<out T>(val value: T) : Result<T>()
data class Error(val exception: Throwable) : Result<Nothing>()
fun safelyDivide(a: Int, b: Int): Result<Int> {
return try {
if (b == 0) {
throw ArithmeticException("Division par zéro")
}
Success(a / b)
} catch (e: Throwable) {
Error(e)
}
}
// Utilisation :
fun processDivision() {
when (val divisionResult = safelyDivide(10, 0)) {
is Success -> println("Résultat : ${divisionResult.value}")
is Error -> println("Erreur : ${divisionResult.exception.message}")
}
}
Il est important de ne capturer que les exceptions que vous pouvez gérer. Il n'est pas conseillé de laisser des blocs catch vides. Si nécessaire, vous pouvez enregistrer l'exception dans un journal.
Il est également possible de lancer explicitement des exceptions avec le mot-clé throw :
fun requirePositive(number: Int) {
if (number <= 0) {
throw IllegalArgumentException("Le nombre doit être positif")
}
}