3 min read

Exception Handling in Java

Exceptions in code are either thrown or caught and handled.
Exception Handling in Java

Working With Exceptions

When working with exceptions, you will either throw them or handle them. Exceptions are thrown when something isn't what it is expected to be. For example, trying to read a file that doesn't exist. When you are executing code that can throw an exception, you can wrap that code in a try block to execute code if a specific exception occurs.

Throwing Exceptions

Exceptions are thrown using a throw statement. Depending on if you are throwing a checked exception or an unchecked exception will change how it is written.

Throwing Unchecked Exceptions

Unchecked exceptions are the easiest to throw. You simply provide a throw statement followed by the exception instance you are throwing.

public void method() {
    throw new UncheckedException();
}

Throwing Checked Exceptions

Throwing a checked exception is written the same as an unchecked exception. The difference between the two is that checked exceptions need to be added to a method signatures throws clause.

public void method() throws CheckedException {
    throw new CheckedException();
}

When you have to specify the checked exceptions in a throws clause, you are generally going to want to list the individual subclasses instead of being too generic and using a superclass.

Try Blocks

When you are executing a method that can throw an exception and you want to handle it, you execute that method in a try block. Try blocks must have a catch block and/or a finally block. This section only shows the try block, which is not valid syntax.

// Partial try block.
try {
    methodThatCanThrowException();
}
// ...

When a method throws an exception, you do not have to handle that exception when the method is invoked. It can be handled anywhere in the call stack.

public void method1() {
    // Partial try block.
    try {
        method2();
    }
    // ...
}

public void method2() {
    method3();
}

public void method3() {
    throw new RuntimeException();
}

Catch Blocks

You can provide a block of code to execute when an exception is thrown by a method. This is called a catch block, and it is written after a try block. Catch blocks will execute based on the exception in the catch block. For example:

public void method() {
    throw new RuntimeException();
}

try {
    method();
} catch (final RuntimeException e) {
    // ...
}

If method() throws a RuntimeException, the block of code executes in the catch block. When specifying a superclass in a catch block, all subclasses of that superclass will be caught in that catch block.

Multiple Catch Blocks

You can have multiple catch blocks. This allows you to execute a different code block depending on the exception that is thrown.

try {
    // ...
} catch (final IOException e) {
    // ...
} catch (final RuntimeException e) {
    // ...
} catch (final Exception e) {
    // ...
}

Union Catch Blocks

Catch blocks also support union catch blocks. You can specify multiple exceptions in a union catch block. If any of the exceptions match, that catch block will execute.

try {
    // ...
} catch (final IOException | RuntimeException e) {
    // ...
}

Finally Blocks

A finally block is a block of code that is written after the catch block(s). A finally block is guaranteed to execute after the try and catch blocks, regardless of whether there was an exception thrown or not. Finally blocks are a good way to clean up resources. When a try block contains a finally block, catch blocks are optional. For example:

try {
    methodThatCanThrowException();
} finally {
    // ...
}

If an exception is thrown, it will execute the finally block and then throw the exception.

try {
    methodThatCanThrowException();
} catch (final Exception e) {
    // ...
} finally {
    // ...
}

If an exception is thrown in the try block, this will execute the catch block first and then the finally block.

Return Statements

Return statements should never be in a finally block. If an exception is thrown and a finally block has a return statement, that exception will be dropped like it was never thrown.

Throw Statements

Throw statements shouldn't be used in a finally block. If a throw statement is in a finally block, it will throw that exception instead of the original exception that was thrown.

Conclusion

Exceptions are caught and handled in try blocks that contain a catch block. Try blocks must have either a catch block or a finally block or both. When using finally blocks, do not use return statements or throw statements.