Kotlin try catch and Exception Handling Tutorial

In this section, we will learn what the exception handling is and how to handle exceptions using the try catch clauses.

What is exception in Kotlin?

Exception at its core, is a misbehavior of a program that might lead to its crash if it’s not handled properly.

For example, let’s say you have a calculator program that takes numbers and runs the related mathematical operation on them.

Now if you didn’t write the program properly to handle situations where users accidentally enter string values (you can’t run mathematical operations on string values), your program throws an exception and will crash.

Now Kotlin has provided methods by which we can implement ways to handle exceptions and stop them from crashing our programs.

Alright, now let’s go and see types of errors in a program and the methods for handling them.

Types of Error in Kotlin

Kotlin is a compile type language! That means our program is first converted (AKA compiled) to executable codes and then the compiled version of the source code will be passed to the execution engine (The JVM in this case) to be run.

So a Kotlin program has two stages in short: compile time and runtime (Runtime is the time that our program is running).

In each of these two stages, error can happen, which will stop a program to proceed and finish that stage.

Now, because of these two stages, we say there are two types of error in Kotlin:

  • Compile time error
  • Runtime Exception

Compile Time Error in Kotlin

A compile time error is the one that happens at compile time and won’t let the source code to fully compile.

These types of errors mostly related to the wrong way of using syntax and the structure of the Kotlin or calling variables, classes, interfaces or functions that didn’t exist in the target program.

For example, if you call a function with the name printFullName() and your program didn’t have such function at all, then an error will occur at compile time.

Example: throwing compile time error in Kotlin

fun main(){

    yar firstName = "John"
    var res = firstName.uppercase()

    println(res)
}

If we try to compile this simple program, we will get a compile time error! This is because we’ve tried to create the variable firstName using yar keyword which doesn’t exist in Kotlin! So Kotlin got confused by seeing that keyword and because it didn’t know how to interpret that word, it threw an error instead.

Let’s see another source of compile time error:

fun main(){

    var firstName = "John"
    var res = firstName.uppercase()

    println(res)

Output:

error: expecting '}'

Note that here we got a compile time error and that’s because the main function needed a closing } curly brace and we forgot to put that for this function.

Runtime Exception in Kotlin

Now runtime exceptions are those that happen while our program is actually running!

Note that we call errors that happen at runtime as exceptions and not errors! The word exception refers to the fact that the program is working properly “except” in certain case or cases.

An exception can happen, for example, if the program took a wrong type of data from users or a request to a resource that didn’t exist, etc.

For example, let’s say our program works with files! Now, if a user asked for a file in a certain directory that didn’t exist, this can easily result to an exception in the program and if not handled properly, it would cause it to crash.

Example: throwing exception in Kotlin

fun main(){
    println("Please enter a number: ")
    var num = readLine()?.toInt()

    var res = num?.div(2)

    println("The result of dividing the number by 2 is: $res")


}

Output:

Please enter a number:

g

Exception in thread "main" java.lang.NumberFormatException: For input string: "g"

Here our program crashed because we’ve putted the character g as the input value for this program.

Now, because this program can’t convert the character g into a number, we got the NumberFormatException exception, which is an exception that happens when the required data for an operation should be of number type, but we pass a value of different data type.

Note that if we passed a correct integer number to the program, things would’ve worked correctly and we didn’t get the exception anymore.

What is Exception Handling in Kotlin?

The process of handling an exception in Kotlin is called exception handling.

In Kotlin, the most famous method of handling exceptions is by using the try-catch blocks.

Note: the try-catch block is designed to handle exceptions that happen at runtime and not those errors that would be caught at compile time!

try catch Blocks in Kotlin

The try and catch blocks are Kotlin way of handling exceptions.

The try clause represents a block where you can write any instructions (codes) that you may think it has the potential to cause an exception.

The catch clause, which comes after each try clause, represents another block which you can write another set of instructions (codes) that will be your solution to the potential exception that might throw in the related `try` block.

Basically, your program first starts by running the instructions on the try block. Now, if no exception raised, then the instructions in the catch block will be skipped. But if an exception happened in the try block, then the catch block that comes with the try block will be invoked and the program runs the instructions within this block.

There are some intricacies related to try and catch blocks, but before we get into that, first let’s see the syntax of the try and catch blocks and then we will continue our discussion related to them.

How to Declare try catch Blocks? (try catch block syntax)

This is how we create a try and catch block in Kotlin:

try {

// The body of the try block

} catch (parameter: ExceptionType){

// The body of the catch block

}

try: In order to create a try block, we start with the try keyword. Note that the pair of curly braces that comes after this keyword defines the body of the try block and we can put any code here that might throw an exception.

catch (parameter:ExceptionType){}: First of all, the catch keyword is used in order to create the handler part of an exception handling. This clause comes after the closing braces of a try clause.

Also note that when declaring a catch clause, it’s like we’re creating a function with one parameter! This is because exceptions in Kotlin are actually objects of different types (BTW, they all inherit from a class called Throwable)! So when creating a catch clause, we need to declare what type of exception this particular catch block is capable of handling! And this is done by setting the data type of the parameter of the catch block.

Note that a try block is capable of having more than just one catch block! For example, if the source code in a try block has this potential to throw two different types of exceptions, then we can create two catch block for the try block that each is capable of handling a specific type of exception.

For example:

try{

}catch(param:ExceptoinType1){

}catch(param:ExceptionType2){

}

How does try catch block work in Kotlin?

As the syntax above shows, when a new exception is thrown from the body of a try block (remember that the thrown exception is an actual object), our program starts by checking the first catch block of that try clause. It checks the data type of the parameter in the first catch block to see if it matches the data type of the thrown exception object. If it did, then the program will pass the reference of this thrown exception to the parameter of the catch clause and run the body of that catch block! BTW, we can use the parameter to access the details of the exception within the body of the target catch.

For example, exception objects have functions that we can call and get a string value which explains the reason of the exception in a human understandable form.

Now if the first catch block of the target try clause didn’t have the right data type for the exception, our program moves on to the second catch block (if any) to see if the data type of the parameter for that catch block matches the data type of the exception object or not.

After this checking process, if types matched then the body of the second catch clause will run, otherwise our program checks the third catch block of the target try clause.

This process continues until one of the catch blocks of the target try clause matches the exception type or no other catch block left to be checked! Which, in that case, the exception will move back to the caller scope!

We will talk about the caller scope later in this section, but for now just remember that if no handler can handle the thrown exception, our program will finally crash.

Kotlin Catch Block Notes:

  • The type of parameter that we set in a catch block should be either of type the Throwable class or a child class that inherits from this class. This is because the Throwable class is considered as the superclass of all other exception types.

For example, two types of exceptions (objects) that might be thrown in a program can both be IndexOutOfBoundsException and NullPointException. Both of these classes inherit from Throwable class.

Example:

try{

}catch(ex: String ){

}

This will return error because the String type is not a subclass of the Throwable class.

But the example below is correct because the IOException is in fact a subclass of the Throwable class:

try{

}catch(ex: IOException ){

}

In inheritance section, we mentioned that a parent class variable (parameter in this case) can store reference to objects of its type and objects of children types. So because the Throwable class is the base class for all other Exception types (subclasses) we can create only one catch block and set its parameter to be of type Throwable. In such case, the target catch-block is able to catch any type of exception that might be thrown at runtime.

Example: exception handling via try catch block

fun main(){
    
    try{
        division(100, 0)
        println("After calling the function in the try block")
    }catch(obj:ArithmeticException){
        println("This is the message of the thrown exception: ")
        println(obj.message)
    }

    println("The message after the try-catch clauses")
}

fun division(val1:Int, val2:Int):Int{

    return val1/val2
}

Output:

This is the message of the thrown exception:

/ by zero

The message after the try-catch clauses

Exception handling and control flow in Kotlin

In the example above, we have one function called division which takes two values, divides them by each other and then returns the result.

Also, we have a try-catch clause in the body of the main function and within the body of the try block we’ve called the division function and passed two arguments 100 and 0.

Now let’s see the flow of control in this simple program:

– Our program enters the body of the try block and sees the call to the division function with the specified arguments.

– So it will invoke the function and start to run the instructions there.

– Here the statement is to divide the value 100 by 0 and return the result. But we know that a number cannot be divided by 0 value!

– So for this reason our program will throw an exception (an object actually) of type ArithmeticException Class.

– Now within the division() function itself, our program will start to look and see if by the time the exception occurred, whether it was surrounded by a try block or not!

– But we can see that the return statement is not surrounded by a try-catch block in this function!

– So now our program returns to the scope of the caller of this function right where the call occurred! (Which is in the try block of the main function).

Note that at this point, the division() function is terminated immediately and nothing returned from the function except for the thrown exception object! (Doesn’t matter how many instructions left in a scope (like this function). The moment an exception is thrown, our program will terminate the normal flow of running instructions and starts to handle the exception first).

– So our program returned to the body of the main function at this time.

– Now the program realizes that the call to the function was surrounded by a try-catch clause and so immediately moves to the handler (or handlers) of this try block.

– Note that our program won’t even run any instructions left in the try block! So the last statement in this block, which is println("After calling the function in the try block") would never get executed! (Basically, the priority of a program when it faces an exception is to first handle that exception).

– So now the program starts by looking at the catch clause of the try statement to see if the data-type of its parameter matched the data-type of the exception that is thrown or not!

– Here the data type matched and so the program passed a reference of the exception to the parameter and starts to run the body of this handler.

– At this time, from the perspective of our program, this catch block is the handler of the exception and so it considers that we have successfully handled the exception!

– So the program is now backed to normal and can continue to run the rest of instructions.

But remember: after our program successfully handled an exception, it will neither return to the place where the exception was thrown nor to the body of the related try block to execute the rest of instructions there!

It will simply jump out of the try-catch clauses and continue to run the instructions after this place. So in our example, after handling the exception, the println(“The message after the try-catch clauses”) statement in the body of the main function is considered as the next statement to be executed and that’s what our program practically did.

That’s how this program ran and handled the exception.

Notes:

  • Only one catch block handles the thrown exception! After that, if there are other catch block sitting after the one that handled the exception, they all will be skipped.
  • A program, after handling an exception, will never return to the place where the exception was thrown. It will continue running the instructions after the entire try and catch clauses that the exception happened and handled there.
  • If no handler was found to handle an exception, our program will finally throw the details of that exception to the standard output stream (the details of where and what exception is thrown) and then stop that program.

Kotlin Throwable Class

The Throwable class is the parent class of every other exception you see in Kotlin. This means using this class you can create a catch clause that is capable of taking other exception type in your program because they all will be a sub-type of this Throwable type.

Also, using the Throwable type, you can create your custom exception type. This is covered in the Kotlin User Defined Exception.

Facebook
Twitter
Pinterest
LinkedIn

Top Technologies