Skip to main content

Advanced Java

Exception Handling

Complete lesson for Exception Handling using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with Java OOP and Collections where relevant.

L1

Basics — Exception Handling

Section: Advanced Java. try, catch, finally, throw, throws, checked vs unchecked, and try-with-resources.

The hierarchy

  • Throwable → Error (JVM disasters: OutOfMemoryError, StackOverflowError) and Exception.
  • RuntimeException (and its children: NullPointerException, IllegalArgumentException, IndexOutOfBoundsException) are **unchecked**.
  • Other Exceptions (IOException, SQLException, ClassNotFoundException) are **checked** — javac forces you to catch or declare them.
KindExamplesMust declare / catch?
CheckedIOException, InterruptedExceptionYes
Unchecked (RuntimeException)NPE, IAE, ClassCastExceptionNo
ErrorOutOfMemoryErrorNo (do not catch routinely)

try, catch, finally, throw, throws

  • try protects statements. catch (Type ex) handles that type or a subclass. Multiple catch blocks go from **specific to general**.
  • finally always runs (except JVM death / System.exit). Use it for cleanup, or prefer try-with-resources.
  • throw raises an exception object. throws on a method advertises checked exceptions callers must handle.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class ExceptionBasics {
    static String read(Path path) throws IOException {
        return Files.readString(path);
    }

    public static void main(String[] args) {
        try {
            System.out.println(read(Path.of("missing.txt")));
        } catch (IOException e) {
            System.out.println("checked: " + e.getClass().getSimpleName());
        } finally {
            System.out.println("done");
        }
    }
}

throw vs throws

KeywordWhereMeaning
throwInside a bodyActually throw this object
throwsMethod signatureThis method may pass that checked exception out
L2

Advanced — Exception Handling

Multi-catch, suppressed exceptions, and design

  • catch (IOException | SQLException e) (Java 7) — e is effectively final.
  • try-with-resources: if close() throws too, that exception is *suppressed* and attached to the primary one (getSuppressed()).
  • Do not catch Exception unless you rethrow or log at a boundary. Empty catch (Exception e) {} hides bugs.
  • Create custom exceptions as checked only when the caller can reasonably recover; otherwise extend RuntimeException.
  • Java does not have C++ destructor unwind for arbitrary objects — use try-with-resources / finally.
L3

Tricky Interview Points

Q1) Checked vs unchecked exceptions?

Answer Checked (Exception minus RuntimeException) must be caught or declared. Unchecked (RuntimeException and Error) need not. Use checked for recoverable environmental failures; unchecked for programming bugs.

Q2) throw vs throws?

Answer throw creates/raises an exception. throws lists checked exceptions a method might propagate.

Q3) Does finally run after return?

Answer Yes. If finally also returns or throws, it overrides the original return/exception. Avoid return in finally.

Q4) Can you catch Error?

Answer Syntactically yes, practically no. Errors mean the JVM is in trouble. Do not write recovery logic for OOME as if it were IOException.

Q5) What is try-with-resources?

Answer try (Resource r = ...) { } auto-closes AutoCloseable resources. Preferred over manual finally close.

Q6) Can a constructor throw?

Answer Yes. If it throws, new fails and the reference is never assigned. Declare checked exceptions on the constructor.

Q7) What is exception chaining?

Answer new ServiceException("save failed", cause) keeps the original stack via getCause(). Always pass the cause when you wrap.

L4

Simple Programs

Custom unchecked exception and multi-catch

class InvalidAgeException extends RuntimeException {
    InvalidAgeException(String message) {
        super(message);
    }
}

public class AgeCheck {
    static void register(int age) {
        if (age < 0 || age > 130) {
            throw new InvalidAgeException("age=" + age);
        }
        System.out.println("ok " + age);
    }

    public static void main(String[] args) {
        try {
            register(200);
        } catch (InvalidAgeException | IllegalArgumentException e) {
            System.out.println(e.getMessage());
        }
    }
}
L5

Problem Solving Tricks

  • Catch the most specific type first.
  • Wrap low-level exceptions with a domain exception *and* the cause.
  • Never use exceptions for normal control flow (e.g. parseInt in a loop instead of a regex/guard).
  • Log once at the boundary; do not log-and-rethrow at every layer.
  • InterruptedException is special: restore the interrupt flag if you cannot throw it (Thread.currentThread().interrupt()).
L6

Practice Programs List

  1. Write a method that parses an int and catches NumberFormatException.
  2. Propagate IOException with throws from a helper to main.
  3. Show that finally prints even when you return inside try.
  4. Create a checked InsufficientFundsException and force the caller to handle it.
  5. Open two closeable resources in one try-with-resources.