Kotlin throw Keyword
last modified April 19, 2025
Kotlin's exception handling system allows explicit throwing of exceptions using
the throw keyword. This tutorial explores the throw
keyword in depth with practical examples.
Basic Definitions
The throw keyword in Kotlin is used to explicitly throw exceptions.
When an exception is thrown, the normal flow of the program is interrupted. The
exception propagates up the call stack until it's caught by a try-catch block.
Throwing Built-in Exceptions
The simplest use of throw is to throw standard Kotlin exceptions.
This example demonstrates throwing an IllegalArgumentException.
package com.zetcode
fun checkAge(age: Int) {
if (age < 0) {
throw IllegalArgumentException("Age cannot be negative")
}
println("Age is valid: $age")
}
fun main() {
try {
checkAge(-5)
} catch (e: IllegalArgumentException) {
println(e.message) // Output: Age cannot be negative
}
}
Here we throw an IllegalArgumentException when the age parameter is
negative. The exception is caught in the main function and its message is
printed. This shows basic exception throwing and handling.
Creating Custom Exceptions
Kotlin allows creating custom exception classes by extending the Exception class. This example shows how to define and throw a custom exception.
package com.zetcode
class InvalidEmailException(message: String) : Exception(message)
fun validateEmail(email: String) {
if (!email.contains("@")) {
throw InvalidEmailException("Invalid email format")
}
println("Email is valid: $email")
}
fun main() {
try {
validateEmail("user.example.com")
} catch (e: InvalidEmailException) {
println(e.message) // Output: Invalid email format
}
}
We define a custom InvalidEmailException class that extends
Exception. The validateEmail function throws this exception when the
email doesn't contain '@'. Custom exceptions make error handling more specific.
Throwing Exceptions in Expressions
Kotlin allows using throw as an expression. This enables throwing
exceptions in places where an expression is expected, like in Elvis operators.
package com.zetcode
fun getLength(str: String?): Int {
return str?.length ?: throw IllegalArgumentException("String cannot be null")
}
fun main() {
try {
println(getLength(null))
} catch (e: IllegalArgumentException) {
println(e.message) // Output: String cannot be null
}
}
Here throw is used as part of an Elvis operator expression. If the
string is null, the exception is thrown. This pattern is common for null checks
in Kotlin.
Rethrowing Exceptions
Sometimes you need to catch an exception, perform some action, and then rethrow it. This example shows how to rethrow exceptions in Kotlin.
package com.zetcode
fun processNumber(str: String) {
try {
val num = str.toInt()
println("Processed number: $num")
} catch (e: NumberFormatException) {
println("Logging error: ${e.message}")
throw e // Rethrow the exception
}
}
fun main() {
try {
processNumber("abc")
} catch (e: NumberFormatException) {
println("Caught rethrown exception") // Output: Caught rethrown exception
}
}
The processNumber function catches a NumberFormatException,
logs it, and then rethrows it. The main function catches the rethrown exception.
This pattern is useful for logging before propagating exceptions.
Throwing Exceptions from Lambdas
Lambdas in Kotlin can throw exceptions just like regular functions. This example shows exception throwing within a lambda expression.
package com.zetcode
fun calculate(operation: (Int, Int) -> Int, a: Int, b: Int): Int {
return try {
operation(a, b)
} catch (e: ArithmeticException) {
println("Calculation error: ${e.message}")
-1
}
}
fun main() {
val result = calculate({ x, y ->
if (y == 0) throw ArithmeticException("Division by zero")
x / y
}, 10, 0)
println(result) // Output: -1
}
The lambda passed to calculate throws an ArithmeticException
when division by zero is attempted. The exception is caught in the calculate
function. This shows how exceptions propagate from lambdas.
Using throw with Nothing Type
In Kotlin, throw has the special type Nothing. This
means it can be used in places where any type is expected. The compiler knows
execution won't continue after a throw.
package com.zetcode
fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}
fun getUser(id: Int): String {
return if (id > 0) {
"User$id"
} else {
fail("Invalid user ID")
}
}
fun main() {
try {
println(getUser(1)) // Output: User1
println(getUser(-1)) // Throws exception
} catch (e: IllegalArgumentException) {
println(e.message) // Output: Invalid user ID
}
}
The fail function returns Nothing, allowing it to be
used where a String is expected in getUser. The compiler knows the
else branch will throw an exception and won't return normally.
Best Practices for Exception Handling
- Use exceptions for exceptional cases: Don't use exceptions for normal flow control.
- Prefer specific exceptions: Throw the most specific exception that fits the error condition.
- Provide meaningful messages: Include helpful information in exception messages.
- Document thrown exceptions: Use Kotlin's documentation to note which exceptions a function might throw.
- Consider alternatives: For recoverable errors, consider using sealed classes or result types instead of exceptions.
Source
Kotlin Exceptions Documentation
This tutorial covered Kotlin's throw keyword in depth, showing how
to throw built-in and custom exceptions. We explored various scenarios including
expression throws, rethrowing, and the Nothing type. Proper exception handling
makes your code more robust and maintainable.
Author
List all Kotlin tutorials.