Error Handling in Kotlin: try/catch and Beyond
Error handling is one of the key tasks when writing reliable and robust code. Kotlin, as a modern programming language, offers developers several powerful tools for working with exceptions and abnormal situations. In this article, we will thoroughly examine the classic try/catch mechanism, null safety features, as well as advanced approaches: using Result and sealed classes. The material will be useful for both beginners and experienced programmers who want to structure their knowledge.
1. Classic try/catch in Kotlin
Kotlin is fully compatible with Java and supports the traditional try/catch/finally block. However, there are important differences: in Kotlin, exceptions are unchecked, meaning the compiler does not force you to handle them. This makes the code more concise but requires attention.
The syntax looks like this:
try { // Code that may throw an exception val result = riskyOperation() println("Result: $result")} catch (e: Exception) { // Exception handling println("An error occurred: ${e.message}")} finally { // Block executes in any case println("Operation completed")}In Kotlin, try can be used as an expression that returns a value:
val number: Int? = try { "123".toInt()} catch (e: NumberFormatException) { null}println(number) // Will print: 123This is especially convenient when you need to get a result or a default value without extra variables.
2. Null Safety: Preventing Errors at the Type Level
One of the main features of Kotlin is null safety. The language solves the NullPointerException problem at the compilation stage. Types in Kotlin are divided into nullable (can be null) and non-null (cannot be null).
Example:
var name: String = "Kotlin" // Cannot be null// name = null // Compilation error!
var nullableName: String? = "Kotlin" // Can be nullnullableName = null // WorksFor safe work with nullable types, Kotlin offers several operators:
- ?. (safe call) — performs an operation only if the value is not null:
val length = nullableName?.length // If null, then nullval length = nullableName?.length ?: 0val length = nullableName!!.length // If null — exceptionUsing null safety instead of try/catch for null checks makes the code more readable and safer.
3. Using Result for a Functional Approach
Kotlin provides a built-in class Result<T>, which represents the result of an operation that can complete successfully or with an error. This is an alternative to try/catch based on functional programming.
Usage example:
fun riskyDivision(a: Int, b: Int): Result<Int> { return runCatching { a / b }}
fun main() { val result = riskyDivision(10, 0)
result.onSuccess { value -> println("Success: $value") }.onFailure { error -> println("Error: ${error.message}") }
// Or you can get a value with a default val value = result.getOrDefault(0) println("Value: $value")}runCatching is a convenient wrapper function that catches any exceptions and returns a Result. You can combine Result with call chains, which