Gestion des erreurs en Kotlin : try/catch et bien plus
La gestion des erreurs est une partie essentielle de l'écriture d'un code fiable et robuste. En Kotlin, comme en Java, il existe le mécanisme classique try/catch/finally, mais le langage propose également des approches plus modernes et fonctionnelles. Dans cet article, nous allons détailler toutes les façons de gérer les exceptions en Kotlin : du try/catch de base à l'élégant runCatching en passant par les puissants Result et sealed class.
1. Le try/catch/finally classique
La syntaxe de base de la gestion des exceptions en Kotlin est pratiquement identique à Java, mais avec une différence importante : try peut être une expression, c'est-à-dire qu'il peut retourner une valeur.
Exemple 1 : try en tant qu'expression
fun parseIntOrNull(input: String): Int? { return try { input.toInt() } catch (e: NumberFormatException) { null }}
fun main() { val result = parseIntOrNull("123") println(result) // 123
val badResult = parseIntOrNull("abc") println(badResult) // null}Exemple 2 : Blocs catch multiples
fun processInput(input: String) { try { val number = input.toInt() val result = 100 / number println("Résultat : $result") } catch (e: NumberFormatException) { println("Erreur : format de nombre invalide") } catch (e: ArithmeticException) { println("Erreur : division par zéro") } finally { println("Le bloc finally s'exécute toujours") }}Le bloc finally s'exécute dans tous les cas — que l'exécution soit réussie ou qu'une exception se produise. C'est pratique pour libérer des ressources (fermeture de fichiers, connexions).
2. L'opérateur Elvis (?:) et les appels sécurisés
Kotlin propose une manière élégante de gérer les valeurs null, ce qui permet souvent d'éviter les constructions lourdes avec try/catch.
Exemple : Conversion sécurisée avec l'opérateur Elvis
fun safeStringToInt(input: String): Int { return input.toIntOrNull() ?: 0 // Si null, on retourne 0}
fun main() { println(safeStringToInt("42")) // 42 println(safeStringToInt("abc")) // 0}La fonction toIntOrNull() est une alternative intégrée à Kotlin pour try/catch. Elle ne lance pas d'exception, mais retourne null en cas d'erreur. L'opérateur Elvis ?: fournit une valeur par défaut.
3. L'approche fonctionnelle : runCatching et Result
Le Kotlin moderne recommande d'utiliser un style fonctionnel pour la gestion des erreurs. Les outils clés sont runCatching et la classe Result.
Exemple : runCatching
import kotlin.Result
fun divide(a: Int, b: Int): Result<Int> { return runCatching { a / b }}
fun main() { val successResult = divide(10, 2) val failureResult = divide(10, 0)
// Gestion du résultat successResult .onSuccess { println("Succès : $it") } // Succès : 5 .onFailure { println("Erreur : ${it.message}") }
failureResult .onSuccess { println("Succès : $it") } .onFailure { println("Erreur : ${it.message}") } // Erreur : / by zero
// Obtention de la valeur avec une valeur par défaut val value1 = successResult.getOrDefault(-1) // 5 val value2 = failureResult.getOrDefault(-1) // -1
// Transformation du résultat val mappedResult = successResult.map { it * 2 } // Result(10)}Avantages de runCatching :
- Le code devient déclaratif et lisible.
- Pas besoin d'écrire manuellement
try/catch. - Le résultat peut être facilement combiné, transformé et traité par des chaînes d'appels (
.map).