Exception Handling Interview Questions

Naveen AnamaneniUpdated · 6 min read

A good school has a plan for things going wrong: a fire drill, a first-aid room, a phone number to call when the bus breaks down. The plan doesn't stop problems happening; it makes sure that when they do, someone deals with them properly and nobody is left stranded. Exception handling is Java's plan for things going wrong, and interviewers ask about it because it separates code that merely works from code that is safe to run in production. This page collects the questions asked most often, from basic to advanced.

Basic Questions

What is an exception?

An event during execution that disrupts the normal flow, represented by an object of a Throwable subclass. When it is thrown, Java looks for a matching catch block up the call stack; if none is found, the thread stops and the stack trace is printed.

What is the exception hierarchy?

Throwable is the root. It has two branches: Error (serious JVM problems such as OutOfMemoryError, which programs shouldn't catch) and Exception. RuntimeException is a subclass of Exception for programming errors such as NullPointerException.

What is the difference between checked and unchecked exceptions?

Checked exceptions (subclasses of Exception but not RuntimeException, such as IOException) must be caught or declared with throws; the compiler checks this. Unchecked exceptions (RuntimeException and its subclasses, and Error) don't need to be declared.

What is the difference between throw and throws?

throw raises an exception: throw new IllegalArgumentException("negative fee");. throws in a method signature declares which checked exceptions the method may pass on to its caller.

Intermediate Questions

When does finally run, and when doesn't it?

It runs after try (and catch, if one ran), whether the block finished normally, returned, or threw. It is skipped only if the JVM stops: System.exit, a crash, or the machine powering off.

What is try-with-resources?

A try (Resource r = ...) statement that closes each resource automatically at the end, in reverse order, even when an exception is thrown. The resource must implement AutoCloseable. If close() also throws, that exception is added to the main one as a suppressed exception.

What is multi-catch?

One catch block for several unrelated exception types: catch (IOException | SQLException e). The variable e is effectively final. The types can't be subclasses of each other.

Can a catch block for Exception come before one for IOException?

No. The more specific IOException block would be unreachable, and the compiler reports an error. Catch blocks must go from the most specific type to the most general.

How do you create a custom exception?

Extend Exception for a checked exception or RuntimeException for an unchecked one, and provide constructors that take a message and a cause: super(message, cause). Give it a name that describes the problem, such as FeeNotPaidException.

Advanced Questions

What is exception chaining?

Wrapping a low-level exception inside a higher-level one, passing it as the cause: throw new ReportException("Report failed", ioException);. The stack trace then shows both, with "Caused by:", so the root cause isn't lost.

What happens if both try and finally throw?

The exception from finally replaces the one from try, and the original is lost. That is one reason to avoid throwing (or returning) from finally, and to prefer try-with-resources, which keeps the original and adds the second as suppressed.

Checked or unchecked: which should a custom exception be?

Use unchecked for programming errors and conditions the caller can't reasonably recover from (most modern APIs and frameworks do this). Use checked when the caller can and should handle the problem, such as a missing file the user can choose again.

What are exception handling best practices?

Catch the most specific type; never swallow exceptions with an empty catch; don't catch Throwable or Error; keep the cause when wrapping; use try-with-resources for anything closeable; fail fast with clear messages; log once, at the place where the exception is handled.

Exceptions in Code

Let's see a custom exception, chaining, try-with-resources and suppressed exceptions together.

FeeService.java▶ Try it
public class FeeService {
    static class FeeNotPaidException extends Exception {
        FeeNotPaidException(String message, Throwable cause) {
            super(message, cause);
        }
    }
 
    static class Register implements AutoCloseable {
        Register() { System.out.println("register opened"); }
 
        int dueFor(String student) {
            if (student.isBlank()) {
                throw new IllegalArgumentException("no name");
            }
            return 1500;
        }
 
        @Override
        public void close() {
            System.out.println("register closed");
            throw new IllegalStateException("close failed");
        }
    }
 
    static int check(String student) throws FeeNotPaidException {
        try (Register r = new Register()) {
            return r.dueFor(student);
        } catch (IllegalArgumentException e) {
            throw new FeeNotPaidException("cannot check fee", e);
        }
    }
 
    public static void main(String[] args) {
        try {
            check(" ");
        } catch (FeeNotPaidException e) {
            System.out.println("caught: " + e.getMessage());
            System.out.println("cause: " + e.getCause().getMessage());
            for (Throwable s : e.getCause().getSuppressed()) {
                System.out.println("suppressed: " + s.getMessage());
            }
        }
    }
}
Output
register opened
register closed
caught: cannot check fee
cause: no name
suppressed: close failed

Explanation:

  1. dueFor(" ") throws IllegalArgumentException. Before the catch runs, try-with-resources closes the register.
  2. close() throws too, but its exception doesn't replace the first one; it is attached as suppressed.
  3. The catch block wraps the original as the cause of a checked FeeNotPaidException, so nothing is lost.

Interview Corner

What is wrong with catch (Exception e) {}?

It silently hides every problem, including bugs such as NullPointerException. The program carries on in a broken state, and nobody knows why. At minimum, log the exception; better, catch only what you can actually handle.

Should you catch NullPointerException?

No. It signals a bug. Find where the null came from and fix it, or check for null at the boundary with Objects.requireNonNull.

Practice

  1. Easy: Write a method parseMarks(String text) that converts text to an int and throws a custom unchecked InvalidMarksException (with the NumberFormatException as its cause) when the text isn't a number.
  2. Harder: Change FeeService so that close() doesn't throw, and run it again. Then explain, in two sentences, the difference between a cause and a suppressed exception.

Quick check: Exceptions

4 questions
1Which must be caught or declared?
2What does throws do?
3What happens to an exception thrown by close() in try-with-resources when the body also threw?
4In which order should catch blocks go?

Key Takeaways

Was this tutorial helpful?

Lesson 572 of 578