Skip to content
CodeKruPro

Predict the output · Java

Exceptions and finally

Which blocks run, in which order, and what is returned.

Learn: try, catch and finally: what Java runs and returns7 minute read

An exception is an object Java throws when something goes wrong, such as dividing an int by zero. A try block marks code that might throw, a catch block handles a given type of exception, and a finally block holds clean-up code. Exception questions ask two things: which blocks run, and what value comes back. Testers use these blocks every day, for example to quit a browser in finally, so interviewers expect you to know these rules well. They are strict and predictable.

Rule 1: a throw skips the rest of the try block

When a statement throws, nothing after it in the try block runs. Java looks at the catch blocks from top to bottom and runs the first one whose type matches the exception or one of its parent classes. (Exception classes form a family tree. For example, RuntimeException is a parent of IllegalArgumentException, so a catch for the parent also catches the child.) Only one catch block runs. If none matches, the exception keeps travelling up to the caller (the method that called this one), and then to that method's caller. If it leaves main, the program stops and prints a stack trace (the list of method calls that led to the error) to standard error, a separate place for error messages; the lines already printed to standard output, the normal printed text, stay.

The compiler rejects a catch block that can never run because an earlier block already catches a parent type. So in code that compiles, the more specific types come first.

Flowchart: if nothing is thrown, finally runs and the code after try continues; if a catch matches, it runs, then finally; if no catch matches, finally runs and the exception goes up to the caller.
Every path through a try statement passes through finally.

Rule 2: finally runs on every way out

A finally block runs whether the try block ends normally, throws, returns, or leaves a loop with break or continue. It even runs when the exception is not caught, just before the exception leaves the method. Only stopping the whole JVM (the Java Virtual Machine, the program that runs Java code), such as with System.exit, skips it.

public class Main {
    static String check(int n) {
        try {
            if (n < 0) {
                throw new IllegalArgumentException("negative");
            }
            return "ok";
        } catch (IllegalArgumentException e) {
            return "error: " + e.getMessage();
        } finally {
            System.out.println("checked " + n);
        }
    }

    public static void main(String[] args) {
        System.out.println(check(1));
        System.out.println(check(-1));
    }
}
checked 1
ok
checked -1
error: negative

Notice the order: checked 1 prints before ok, because main can print the result only after check has fully returned, and finally runs before that.

Rule 3: the return value is saved before finally runs

When return x runs inside try, the value of x is saved first. Then finally runs. If finally assigns a new value to x, the saved value does not change. If x refers to a mutable object and finally changes that object, the caller sees the change, because the saved value is the reference.

public class Main {
    static int value() {
        int x = 10;
        try {
            return x;
        } finally {
            x = 20;
            System.out.println("x is now " + x);
        }
    }

    public static void main(String[] args) {
        System.out.println(value());
    }
}
x is now 20
10

Rule 4: finally can override everything

A return inside finally replaces the pending return value and also discards a pending exception. An exception thrown inside finally replaces the exception that was already on its way, and the first one is lost. Both are reasons to use finally only for clean-up.

Rule 5: try-with-resources closes in reverse order

A resource is something that must be closed after use, such as a file or a database connection. Resources declared in try (...) must implement AutoCloseable, which means the class promises to have a close method. They are opened in the order written and closed in reverse order as soon as the block ends, before any catch or finally of the same statement runs. If close also throws, that exception is attached to the main one as a suppressed exception (a second error stored inside the first, so it is not lost) instead of replacing it.

public class Main {
    record Step(String name) implements AutoCloseable {
        Step {
            System.out.println("open " + name);
        }

        public void close() {
            System.out.println("close " + name);
        }
    }

    public static void main(String[] args) {
        try (Step a = new Step("A"); Step b = new Step("B")) {
            System.out.println("work");
        } finally {
            System.out.println("finally");
        }
    }
}
open A
open B
work
close B
close A
finally

How to answer in an interview

Trace the snippet aloud: which line throws, which catch matches, then finally, then what happens next. For "does finally always run?", answer "yes, on return, break, continue and exceptions; only stopping the JVM skips it", and add that a return in finally hides errors, so you never write one. Checked and unchecked exceptions differ only at compile time (before the program runs; for a checked one, the compiler makes you catch it or declare it); at run time both travel and are caught the same way.

Common mistakes

  • Printing the line after the throw inside the try block.
  • Running more than one catch block.
  • Printing the returned value before the finally output.
  • Thinking finally can change a returned int.
  • Closing resources in the order they were opened.

Recap

A throw skips the rest of try, the first matching catch runs, and finally runs on every way out. The return value is fixed before finally runs, but a return or throw inside finally overrides it. Resources close in reverse order, before catch and finally.

10 questions0/10 solved

Not startedNot startedIn progressIn progressSolvedSolvedPro+Pro+

The first 2 questions of each topic are free. Pro+ opens every question.

Back to the plan