Skip to content
  • try/catch/finally & try-with-resources · Java

try/catch/finally & try-with-resources

LearnViaNotes @learnvianotes· 4 min read

try marks code that may fail, catch handles specific exceptions, finally always runs — and try-with-resources closes resources automatically, in reverse order, without losing exceptions.

Anatomy

Java
public class Main {
    static void run(String input) {
        try {
            System.out.println("parsing " + input);
            int n = Integer.parseInt(input);
            System.out.println("100 / n = " + 100 / n);
        } catch (NumberFormatException | ArithmeticException e) {   // multi-catch
            System.out.println("bad input: " + e.getClass().getSimpleName());
        } finally {
            System.out.println("finally");                          // always
        }
    }

    public static void main(String[] args) {
        run("4");
        run("0");
        run("x");
    }
}
Output
parsing 4
100 / n = 25
finally
parsing 0
bad input: ArithmeticException
finally
parsing x
bad input: NumberFormatException
finally
  • Catch blocks are tried top to bottom; the first matching type wins.

  • A subclass catch must come before its superclass — catch (Exception e) then catch (IOException e) doesn't compile (unreachable).

  • In a multi-catch A | B, the types can't be related by inheritance and e is implicitly final.

  • try needs at least one catch or a finally (or resources).

finally always runs — even after return

Java
public class Main {
    static int value() {
        try {
            return 1;
        } finally {
            System.out.println("finally runs before the method returns");
        }
    }

    @SuppressWarnings("finally")
    static int overridden() {
        try {
            throw new RuntimeException("lost!");
        } finally {
            return 2;              // discards the exception AND any earlier return
        }
    }

    static int snapshot() {
        int x = 10;
        try {
            return x;              // return value (10) is saved here
        } finally {
            x = 99;                // changing x doesn't affect it
        }
    }

    public static void main(String[] args) {
        System.out.println(value());
        System.out.println(overridden());
        System.out.println(snapshot());
    }
}
Output
finally runs before the method returns
1
2
10

try-with-resources

Any object implementing AutoCloseable (or Closeable) declared in the try (…) header is closed automatically when the block ends — normally or by exception. Resources close in reverse order of declaration.

Java
public class Main {
    record Res(String name) implements AutoCloseable {
        Res { System.out.println("open " + name); }
        @Override public void close() { System.out.println("close " + name); }
    }

    public static void main(String[] args) {
        try (Res db = new Res("db"); Res file = new Res("file")) {
            System.out.println("working with " + db.name() + " and " + file.name());
            throw new IllegalStateException("failure");
        } catch (IllegalStateException e) {
            System.out.println("caught " + e.getMessage() + " (resources already closed)");
        } finally {
            System.out.println("finally");
        }
    }
}
Output
open db
open file
working with db and file
close file
close db
caught failure (resources already closed)
finally

Suppressed exceptions

If the body throws and close() throws, the body's exception is the one propagated; the close exception is attached to it as suppressed instead of replacing it (which is what a hand-written finally { close(); } would do).

Java
public class Main {
    static class Conn implements AutoCloseable {
        @Override public void close() { throw new IllegalStateException("close failed"); }
    }

    public static void main(String[] args) {
        try (Conn c = new Conn()) {
            throw new RuntimeException("query failed");
        } catch (RuntimeException e) {
            System.out.println("primary: " + e.getMessage());
            for (Throwable s : e.getSuppressed())
                System.out.println("suppressed: " + s.getMessage());
        }
    }
}
Output
primary: query failed
suppressed: close failed

Before and after

Does finally run if there's a return in try?

When does finally NOT execute?

What are suppressed exceptions?

In what order are resources closed?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report