In this tutorial, we’ll be discussing Exception Handling in Kotlin.
Table of Contents
What are Exceptions?
Exceptions are something that can break your program. That makes Exception Handling an essential part of any Programming Language. Using Exception handling you can handle errors and prevent runtime crashes that can stop your program. Instead, using Exception Handling you can handle failed conditions gracefully and continue with your program flow.
Checked Exceptions are typically set on methods and are checked at compile time.
On the contrary, Unchecked exceptions derive from RuntimeExceptions and are checked at runtime.
Kotlin Exceptions
All Exceptions descend from the Throwable class.
To throw an exception we use the throw
keyword.
throw Exception("Oops. Something went wrong")
In Kotlin there are no checked exceptions. That means there is no throws keyword.
try-catch-finally
To handle exceptions we use the try-catch
block. The piece of code that has a possibility to give an exception is set inside the try block. The exception is caught inside the catch block. Irrespective of what happens, the finally block is always run.
The finally blocks is optional. It’s generally used to release any resources that were used in the try-catch.
Typically a try can have multiple catches. Only the first matching catch would be run. Hence it’s recommended to stack the catches in the order: Specific Exception to General Exception.
fun main(args: Array<String>) {
try {
var a = 0
var x = 7 / a
val v = "Journaldev.com"
v.toInt()
} catch (e: ArithmeticException) {
println("Arthimetic Exception")
} catch (e: Exception) {
println("Exception occured. To print stacktrace use e")
} finally {
println("Finally. It's over")
}
}
//Prints
//Arthimetic Exceptions
Once an exception in the try
block is found, it’ll not execute anything else in that try block.
We can even use a try
with a finally
.
try{
throw Exception("Hi. how are you?")
}finally {
println("Finally. Good.")
}
With a try, at least one catch or finally block must be present.
throw
is an expression which would print the stack trace as well.
Try is an expression
The value executed in a try-catch block can be returned and stored in a variable.
fun main(args: Array<String>) {
var x= "Androidly.net"
var a = try { x.toInt() } catch (e: NumberFormatException) { "This is a string" }
println(a)
x = "5"
a = try { x.toInt() } catch (e: NumberFormatException) { "This is a string" }
println(a)
}
In the above code, we’re able to set the variable a with two different type of values.
If the try statement doesn’t execute the value of catch is set.
Irrespective of which is set, the finally
statement is never set as the expression.
fail function
This is a shorthand for catching exceptions as shown below.
import kotlin.test.fail
class User {
var name: String? = ""
}
fun main(args: Array<String>) {
var user = User()
user.name = null
val n: String = user.name ?: fail("No name found")
print(5)
}
If the fail statement is executed the program won’t run after it’s printed.
Implicitly the fail statement contains a throw keyword.
The fail function looks like this:
fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}
Nothing is a special return type which throw returns.
In the above example, the fail function prints the stack trace too which we don’t always want.
We can override the fail function to just print the message.
class User {
var name: String? = ""
}
fun main(args: Array<String>) {
var user = User()
user.name = null
val n: String = user.name ?: fail("No name found")
println(n)
print(10)
}
fun fail(message: String): Nothing {
val throwable = Throwable(message)
Thread.setDefaultUncaughtExceptionHandler { t, e -> System.err.println(e.message) }
throw throwable
}
//Prints
No name found
Using Inline Functions with exception handling
We’ve discussed Inline Functions in Kotlin here.
Why use Inline Functions?
They cause no overhead.
Now, we’ve seen that try-catch blocks can get messy and verbose.
Let’s use an inline function to make it concise since that’s where the strength of Kotlin code lies in.
fun main(args: Array<String>) {
simpleTryCatch {
var x = 0
var y = 7
var z = y / x
}
simpleTryCatch {
var x = "Androidly"
var number = x.toInt()
}
}
inline fun simpleTryCatch(action: () -> Unit) {
try {
action()
} catch (t: Throwable) {
println("Caught something. ${t.message}")
}
}
This brings an end to this Kotlin tutorial on Exception handling.
Is using fail ever advisable except for when writing tests? Looks like a bad idea to use that in Standard SDE use cases.