Sobes.tech
Junior

Ako správne spracovať výnimky v Kotlin?

sobes.tech AI

Odpoveď od AI

V Kotlinu sa spracovaním výnimiek používa konštrukcia try...catch...finally. Môžete volať funkcie označené ako @Throws na interakciu s Java kódom.

fun readFile(path: String): String {
    return try {
        // Pokus o vykonanie nebezpečného kódu
        java.io.File(path).readText()
    } catch (e: java.io.IOException) {
        // Spracovanie konkrétnej výnimky
        println("Chyba pri čítaní súboru: ${e.message}")
        "" // Vrátenie predvolenej hodnoty pri chybe
    } finally {
        // Blok, ktorý sa vykoná vždy, bez ohľadu na výnimku
        println("Pokús o čítanie súboru je ukončený")
    }
}

Je možné použiť viacero blokov catch na spracovanie rôznych typov výnimiek:

fun processData(data: String) {
    try {
        // Kód, ktorý môže vyvolať NumberFormatException alebo NullPointerException
        val number = data.toInt()
        println("Číslo: $number")
    } catch (e: NumberFormatException) {
        println("Neplatný formát čísla: ${e.message}")
    } catch (e: NullPointerException) {
        println("Získané nulové údaje: ${e.message}")
    }
}

Kotlin nemá checked výnimky ako v Jave. Funkcie môžu deklarovať, že môžu vyhodiť výnimky pomocou @Throws, ale to nie je povinné pre Kotlin kód.

Pre prípady, keď funkcia môže skončiť úspešne alebo s chybou, sa často používajú sealed triedy alebo Result typ (v experimentálnych verziách Kotlinu) namiesto výnimiek, najmä v asynchrónnom kóde.

Príklad so sealed triedou:

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

// Použitie:
fun processDivision() {
    when (val divisionResult = safelyDivide(10, 0)) {
        is Success -> println("Výsledok: ${divisionResult.value}")
        is Error -> println("Chyba: ${divisionResult.exception.message}")
    }
}

Je dôležité zachytiť iba tie výnimky, ktoré môžete spracovať. Nie je vhodné nechať prázdne catch bloky. V prípade potreby môžete zaznamenať informácie o výnimke do logu.

Tiež je možné výnimky vyhodiť explicitne pomocou kľúčového slova throw:

fun requirePositive(number: Int) {
    if (number <= 0) {
        throw IllegalArgumentException("Číslo musí byť kladné")
    }
}