Sobes.tech
Junior

Hoe behandel je uitzonderingen correct in Kotlin?

sobes.tech AI

Antwoord van AI

In Kotlin wordt exception handling gedaan met de constructie try...catch...finally. Je kunt functies aanroepen die gemarkeerd zijn met @Throws om interactie met Java-code mogelijk te maken.

fun readFile(path: String): String {
    return try {
        // Poging om gevaarlijke code uit te voeren
        java.io.File(path).readText()
    } catch (e: java.io.IOException) {
        // Afhandeling van een specifiek exception
        println("Fout bij het lezen van het bestand: ${e.message}")
        "" // Standaardwaarde bij fout
    } finally {
        // Blok dat altijd wordt uitgevoerd, ongeacht de uitzondering
        println("Bestand lezen voltooid")
    }
}

Je kunt meerdere catch-blokken gebruiken om verschillende soorten exceptions af te handelen:

fun processData(data: String) {
    try {
        // Code die een NumberFormatException of NullPointerException kan veroorzaken
        val number = data.toInt()
        println("Nummer: $number")
    } catch (e: NumberFormatException) {
        println("Ongeldig nummerformaat: ${e.message}")
    } catch (e: NullPointerException) {
        println("Ontvangen null-gegevens: ${e.message}")
    }
}

Kotlin heeft geen checked exceptions zoals Java. Functies kunnen aangeven dat ze exceptions kunnen gooien met @Throws, maar dit is niet verplicht.

Voor gevallen waarin een functie succesvol of fout kan eindigen, worden vaak sealed classes of het Result-type (in experimentele Kotlin-versies) gebruikt in plaats van exceptions, vooral in asynchrone code.

Voorbeeld met sealed class:

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("Delen door nul")
        }
        Success(a / b)
    } catch (e: Throwable) {
        Error(e)
    }
}

// Gebruik:
fun processDivision() {
    when (val divisionResult = safelyDivide(10, 0)) {
        is Success -> println("Resultaat: ${divisionResult.value}")
        is Error -> println("Fout: ${divisionResult.exception.message}")
    }
}

Het is belangrijk om alleen die exceptions te vangen die je kunt afhandelen. Vermijd lege catch-blokken. Indien nodig, log de exception.

Je kunt ook expliciet exceptions gooien met throw:

fun requirePositive(number: Int) {
    if (number <= 0) {
        throw IllegalArgumentException("Het getal moet positief zijn")
    }
}