Skip to content

Lesson 03 · try-with-resources & Custom Exceptions

Objectives

After this lesson you will be able to:

  • Use try-with-resources to close AutoCloseable resources automatically.
  • Explain close order and suppressed exceptions.
  • Design and throw custom exceptions.

try-with-resources

Any resource implementing AutoCloseable (or Closeable) declared in the try (...) header is closed automatically — in reverse order of declaration — after the block, even on exception. No finally needed.

java
try (var in = Files.newInputStream(src);
     var out = Files.newOutputStream(dst)) {     // out closed first, then in
    in.transferTo(out);
}   // close() called automatically here

Exam trap

Resources close in reverse declaration order, before any catch/finally runs. Since Java 9 you can also list an effectively final existing variable in the header (try (existingResource) { … }) instead of declaring a new one. A resource variable is implicitly final — you can't reassign it inside the block.

Suppressed exceptions

If the try body throws and close() also throws, the body's exception wins (propagates) and the close() exception is attached as a suppressed exception — retrieve it with getSuppressed().

java
try (var r = new Noisy()) {     // close() throws
    throw new RuntimeException("primary");
}
// Propagates "primary"; the close() exception is in primary.getSuppressed()

Gotcha

This is the opposite of a finally that throws: there, the finally's exception replaces the original. With try-with-resources the primary (body) exception is preserved and the close failure is suppressed.

Custom exceptions

Extend Exception (checked) or RuntimeException (unchecked). Provide constructors that accept a message and a cause so stack traces chain.

java
class InsufficientFundsException extends RuntimeException {
    InsufficientFundsException(String msg, Throwable cause) {
        super(msg, cause);          // chain the cause
    }
}
throw new InsufficientFundsException("balance too low", sqlError);

SDET note

Prefer unchecked custom exceptions for programming/precondition violations and reserve checked ones for recoverable conditions a caller should handle. In tests, assert both the type and message: assertThrows(InsufficientFundsException.class, …) and inspect getCause() when chaining matters.

Key Takeaways

  • try-with-resources auto-closes any AutoCloseable, in reverse declaration order, beforecatch/finally. Resource variables are implicitly final.
  • When body and close() both throw, the body exception propagates and the close failure is a suppressed exception (getSuppressed()).
  • Build custom exceptions by extending Exception (checked) or RuntimeException (unchecked); pass a cause to super to chain.

Lesson Quiz

Lesson Quiz · try-with-resources & Custom Exceptions0 / 5
  1. In which order are resources closed?

    try (A a = ...; B b = ...) { }
    • Aa then b
    • Bb then a
    • CUnspecified
    • DBoth at once
  2. Body throws "primary"; the resource's close() also throws. What propagates?

    • AThe close() exception
    • B"primary", with close() suppressed
    • CBoth wrapped
    • DNeither — swallowed
  3. What interface must a try-with-resources resource implement?

    • ASerializable
    • BAutoCloseable
    • CIterable
    • DRunnable
  4. Can you reassign a try-with-resources resource variable inside the block?

    • AYes
    • BNo — it is implicitly final
    • COnly if not null
    • DOnly the last one
  5. How do you preserve the original error when throwing a custom exception?

    • AIgnore it
    • BPass it as the cause to super(msg, cause)
    • CPrint it
    • DRe-throw it separately

Next: Module 04 Mini-Exam. Run the matching code in labs/src/main/java/com/jse21/m04_exceptions/.