Contents

Catching exceptions in java

Written by: David Vlijmincx

Introduction

An Exception is thrown when your code doesn't know how to handle an unexpected situation. Java is signaling to you that it doesn't know how to handle the current situation and that you need to implement some exception handling if you want to help the code continue to run.

Using Try and Catch blocks

When Java throws an exception at you. You can catch it with a try-catch statement. We use the Try block to separate the code that throws the exception from the code that handles the exception.

The syntax of a try-catch is as follows:

1
2
3
4
5
try {

} catch (ExceptionType parameterName) {

}

The catch block will only run when an exception is thrown that matches the parameter of the catch block. In the following example, we have a catch block that will only run when an unchecked exception is thrown (a RuntimeException or an exception inheriting from the RuntimeException class). If fail() would throw a checked exception like IOException instead of RuntimeException we needed to implement new a catch block to also handle IO exceptions.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
void randomMethod() {
    try {
        fail();
    } catch (RuntimeException e) {
        System.out.println("I give up, " + e.getMessage());
    }
}

void fail() {
    throw new RuntimeException("unexpected exception");
}

Multiple Catch blocks

You can add more than one catch block to a try block to have different behavior for each exception. The order is important when you have multiple catch blocks because exceptions can inherit from each other. For example, IOException inherits from Exception.

In the following example, the catch blocks are in the correct order. When the exception is thrown, Java is going to try and find the first catch block that matches the type of the exception.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
void randomMethod() {
    try {
        fail();
    } catch (IOException e) {
        System.out.println("IOExceptions");
    } 
    catch (Exception e) {
        System.out.println("Any Exception");
    }
}

void fail() throws IOException {
    throw new IOException();
}

Why the order Catch block order is important

In the following example, the order of the catch blocks is incorrect. When an IOException is thrown, the first Catch block will match with this type of exception. Because as we already saw earlier, IOException inherits from Exception. The first catch block will catch every exception making the second catch block unreachable and your code unable to compile.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
void randomMethod() {
    try {
        fail();
    } catch (Exception e) {
        System.out.println("Any Exception");
    } 
    catch (IOException e) {
        System.out.println("IOExceptions");
    }
}

Catching multiple exceptions with one Catch block

You can also use a single catch block to catch two different kinds of exceptions. In the example below, we have two exceptions in the same block separated by a single pipe (|). You don't have to create two parameter names both exceptions will be accessible by the same parameter name e in this case.

1
2
3
4
5
try {
    fail();
} catch (IOException | RuntimeException e) {
    System.out.println("Caught a IOExceptions or RuntimeException");
}

Multi-Catch block rules

Like with the multiple catch block, there is a rule when catching two kinds of exceptions with the same catch block. The Exceptions in the catch statement can't inherit from each other. If they do inherit from each other, you will get a Types in multi-catch must be disjoint error, and your code won't be able to compile.

1
2
3
4
5
try {
    fail();
} catch (IOException | Exception e) {
    System.out.println("Won't compile, because the exceptions inherit from each other");
}

Conclusion

In this post, we went over the basics of catching exceptions. We saw how to catch an exception with one or more catch blocks and using a pipe inside a catch block. We also covered two rules you have to adhere to when catching exceptions.