Skip to content
Exception Handling
step 1/7

Reading — step 1 of 7

Learn

~3 min readInheritance and Interfaces

Real programs encounter errors — invalid input, missing files, network failures, division by zero. Java's exception handling lets you signal failures via the type system and respond to them in dedicated paths. Oracle's Java Tutorials chapter 11 treats this as essential.

try / catch / finally

try {
    int n = Integer.parseInt(input);
    int result = 100 / n;
    System.out.println("result: " + result);
} catch (NumberFormatException e) {
    System.out.println("not a valid number: " + e.getMessage());
} catch (ArithmeticException e) {
    System.out.println("can't divide by zero");
} finally {
    System.out.println("cleanup");
}
  • try block — code that might throw
  • catch blocks — handle specific exception types (multiple OK, ordered most-specific to least)
  • finally block — always runs, even if exception was thrown or caught. For cleanup.

throw — signal a problem

public int divide(int a, int b) {
    if (b == 0) {
        throw new ArithmeticException("divide by zero");
    }
    return a / b;
}

The throw statement creates and propagates an exception. Until something catches it (or the program crashes).

throws — declare a method might throw

public String readFile(String path) throws IOException {
    return Files.readString(Paths.get(path));
}

Checked exceptions (subclasses of Exception but not RuntimeException) MUST be either caught or declared with throws in the method signature. The compiler enforces this.

Unchecked exceptions (subclasses of RuntimeException) don't require declaration — programmer errors like NPE, array out-of-bounds, illegal arguments.

The hierarchy

Throwable
├── Error                      (JVM-level — don't catch)
└── Exception
    ├── RuntimeException        (UNCHECKED)
    │   ├── NullPointerException
    │   ├── IllegalArgumentException
    │   ├── ArithmeticException
    │   └── IndexOutOfBoundsException
    └── (other Exception)       (CHECKED — must declare or catch)
        ├── IOException
        ├── SQLException
        └── ...

Catch the specific type you intend to handle. Catching Exception (or worse, Throwable) hides bugs.

Multi-catch (Java 7+)

try { ... }
catch (IOException | SQLException e) {
    log("data layer failed: " + e.getMessage());
}

Handle multiple exception types in one block when the response is the same.

try-with-resources (Java 7+)

For anything that implements AutoCloseable (Stream, BufferedReader, Connection):

try (BufferedReader br = Files.newBufferedReader(Paths.get("data.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
}   // br.close() automatically — even if exception thrown

Replaces the old try/finally close() pattern. Always use it for resources.

Custom exceptions

public class ValidationException extends Exception {
    private final String field;
    
    public ValidationException(String field, String message) {
        super(message);
        this.field = field;
    }
    
    public String getField() { return field; }
}

throw new ValidationException("email", "invalid format");

Extend RuntimeException for unchecked, Exception for checked. Use checked when the caller MUST handle the failure; unchecked for programmer errors.

Common mistakes

  • Catching Exception to silence errors — hides bugs. Catch the specific type you can handle.
  • Empty catch blockscatch (Exception e) {} is the worst pattern in Java. At least log it.
  • Not closing resources — leaks file handles, connections. Use try-with-resources.
  • Wrapping everything in try-catch "just in case" — if you can't meaningfully handle it, let it propagate to a higher-level handler.
  • Using exceptions for control flow — exceptions are slow and confusing for normal cases. Use them for actual exceptional cases.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…