Kotlin Nested try block and multiple catch block
In Kotlin, exception handling allows developers to manage errors gracefully and prevent application crashes. In this article, we will explore two advanced exception handling concepts in Kotlin:
- Nested try-catch blocks
- Multiple catch blocks, including how to simplify them using a when expression.
Nested try block
A nested try block is when you place one try-catch block inside another. This is useful when different parts of your code may throw different types of exceptions, and you want to handle them at different levels. If an exception occurs inside the inner try block and is not handled by its corresponding catch, the outer catch block is checked next. This allows for layered or fallback error handling.
Syntax -
try {
// Outer try block
try {
// Inner try block
// Code that may throw exception
} catch (e: SomeException) {
// Handle specific exception for inner block
}
} catch (e: SomeException) {
// Handle exception not caught by inner block
}
Example:
fun main() {
val numbers = arrayOf(1, 2, 3, 4)
val a = 10
val b = 0
try {
try {
println(numbers[2]) // Valid index
println(numbers[4]) // Invalid index (will throw ArrayIndexOutOfBoundsException)
} catch (e: ArrayIndexOutOfBoundsException) {
println(e)
}
try {
val result = a / b // Will throw ArithmeticException
println(result)
} catch (e: NullPointerException) {
println("Null pointer error occurred.")
}
} catch (e: ArithmeticException) {
println(e)
}
}
Output:
3
java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
java.lang.ArithmeticException: / by zero
Note: Since the value of b is hardcoded to 0, and the array has only 4 elements (index 0–3), exceptions will always occur in this example. You can experiment with different values for different results.
Multiple catch blocks
In Kotlin, a single try block can be followed by multiple catch blocks. This is helpful when the code inside the try block can throw different types of exceptions, and you want to handle each type separately.
Syntax -
try {
// Code that may throw different types of exceptions
} catch (e: ExceptionType1) {
// Handle ExceptionType1
} catch (e: ExceptionType2) {
// Handle ExceptionType2
}
Example:
fun main() {
val input = readLine() ?: "0"
try {
val num = input.toInt()
val result = 100 / num
println("Result: $result")
} catch (e: NumberFormatException) {
println("Number Format Exception: Please enter a valid integer.")
} catch (e: ArithmeticException) {
println("Arithmetic Exception: Cannot divide by zero.")
}
}
Input 1:
GeeksforGeeks
Output 1:
Number Format Exception: Please enter a valid integer.
Input 2:
0
Output 2:
Arithmetic Exception: Cannot divide by zero.
If the user inputs a non-integer string like "GeeksforGeeks", toInt() throws a NumberFormatException. If the user inputs 0, division by zero causes an ArithmeticException.
Replacing Multiple catch Blocks with when Expression
Kotlin allows you to simplify multiple catch blocks by using a when expression inside a single catch block. This approach improves code readability, especially when you want to perform different actions based on the type of exception.
Example:
fun main() {
val input = readLine() ?: "0"
try {
val num = input.toInt()
val result = 100 / num
println("Result: $result")
} catch (e: Exception) {
when (e) {
is NumberFormatException -> println("Number Format Exception")
is ArithmeticException -> println("Arithmetic Exception: Divide by zero")
else -> println("Some other exception occurred: ${e.message}")
}
}
}
Input 1:
GeeksforGeeks
Output 1:
Number Format Exception
Input 2:
0
Output 2:
Arithmetic Exception: Divide by zero