Error Handling in Kotlin: try/catch and Advanced Techniques

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Error Handling in Kotlin: try/catch and Beyond



Error handling is an essential part of writing reliable and robust code. In Kotlin, like in Java, there is a classic try/catch/finally mechanism, but the language also offers more modern, functional approaches. In this article, we will thoroughly examine all ways of handling exceptions in Kotlin: from basic try/catch to elegant runCatching and powerful Result and sealed class.



1. Classic try/catch/finally

The basic syntax for exception handling in Kotlin is almost identical to Java, but with one important difference: try can be an expression, meaning it can return a value.



Example 1: try as an 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}


Example 2: Multiple catch blocks

fun processInput(input: String) {    try {        val number = input.toInt()        val result = 100 / number        println("Result: $result")    } catch (e: NumberFormatException) {        println("Error: invalid number format")    } catch (e: ArithmeticException) {        println("Error: division by zero")    } finally {        println("The finally block always executes")    }}


The finally block executes in any case — both on successful execution and when an exception occurs. This is convenient for releasing resources (closing files, connections).



2. Elvis Operator (?:) and Safe Calls

Kotlin offers an elegant way to handle null values, which often helps avoid cumbersome try/catch constructs.



Example: Safe conversion with the Elvis operator

fun safeStringToInt(input: String): Int {    return input.toIntOrNull() ?: 0 // If null, return 0}

fun main() { println(safeStringToInt("42")) // 42 println(safeStringToInt("abc")) // 0}


The toIntOrNull() function is a built-in Kotlin alternative to try/catch. It does not throw an exception but returns null on error. The Elvis operator ?: substitutes a default value.



3. Functional Approach: runCatching and Result

Modern Kotlin recommends using a functional style for error handling. The key tools are runCatching and the Result class.



Example: 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)

// Handling the result successResult .onSuccess { println("Success: $it") } // Success: 5 .onFailure { println("Error: ${it.message}") }

failureResult .onSuccess { println("Success: $it") } .onFailure { println("Error: ${it.message}") } // Error: / by zero

// Getting a value with a default val value1 = successResult.getOrDefault(-1) // 5 val value2 = failureResult.getOrDefault(-1) // -1

// Transforming the result val mappedResult = successResult.map { it * 2 } // Result(10)}


Advantages of runCatching:

  • The code becomes declarative and readable.
  • No need to manually write try/catch.
  • The result can be easily combined, transformed, and processed with call chains (.map

Blogs

Book Recommendations