Exception Handling: Keep Programs Robust

Introduction

An exception is an event that disrupts normal flow—invalid input, missing file, network failure. Java exception handling lets you recover, inform users, and release resources instead of crashing silently. This chapter covers try-catch-finally, throws, checked vs unchecked exceptions, and custom types—preparing you for Multithreading (InterruptedException).

Prerequisites

Exception Hierarchy (Simplified)

text
Throwable
├── Error          (serious JVM issues — rarely catch)
└── Exception
    ├── RuntimeException   (unchecked)
    └── other Exception    (checked)

Common types:

ExceptionTypical cause
NullPointerExceptioncall on null
IllegalArgumentExceptionbad argument
NumberFormatExceptionInteger.parseInt("abc")
IndexOutOfBoundsExceptionbad array/list index
IOExceptionfile/network I/O (checked)

1) try / catch

java
try {
    int number = Integer.parseInt("42");
    System.out.println(number);
} catch (NumberFormatException e) {
    System.out.println("Invalid number: " + e.getMessage());
}

Catch specific types first, broader types later.

java
try {
    int a = Integer.parseInt("10");
    int b = Integer.parseInt("0");
    System.out.println(a / b);
} catch (NumberFormatException e) {
    System.out.println("Invalid integer input.");
} catch (ArithmeticException e) {
    System.out.println("Division by zero.");
}

2) finally

Runs whether or not an exception occurred—cleanup (close resources).

java
Scanner scanner = new Scanner(System.in);
try {
    int x = Integer.parseInt(scanner.nextLine());
    System.out.println(x);
} catch (NumberFormatException e) {
    System.out.println("Invalid input.");
} finally {
    scanner.close();
    System.out.println("Done.");
}

Prefer try-with-resources when classes implement AutoCloseable:

java
try (Scanner scanner = new Scanner(System.in)) {
    // use scanner
}  // close() called automatically

3) throw and Custom Exceptions

java
static void setAge(int age) {
    if (age < 0 || age > 130) {
        throw new IllegalArgumentException("Age must be 0–130");
    }
    System.out.println("Age set: " + age);
}

Custom checked exception:

java
public class ScoreOutOfRangeException extends Exception {
    public ScoreOutOfRangeException(String message) {
        super(message);
    }
}
 
static void validateScore(int score) throws ScoreOutOfRangeException {
    if (score < 0 || score > 100) {
        throw new ScoreOutOfRangeException("Score must be 0–100");
    }
}

4) Checked vs Unchecked

CheckedUnchecked (RuntimeException)
Compile-timemust handle or declare throwsoptional to catch
ExamplesIOException, SQLExceptionNullPointerException, IllegalArgumentException
Use whenrecoverable external failuresprogramming errors, often avoidable
java
public void readFile() throws IOException {
    // caller must handle or declare
}
java
try {
    readFile();
} catch (IOException e) {
    System.out.println("Cannot read file: " + e.getMessage());
}

Modern APIs often use unchecked exceptions for cleaner call sites—but checked exceptions still appear in I/O (File Handling).

5) Multi-catch and Rethrow (Java 7+)

java
try {
  // ...
} catch (IOException | SQLException e) {
    System.out.println(e.getMessage());
}

Rethrow with context:

java
catch (IOException e) {
    throw new RuntimeException("Failed to load config", e);
}

Common Beginner Mistakes

Empty catch Blocks

Swallows errors—at least log e.getMessage().

Catching Exception Everywhere

Hides bugs. Catch specific types.

Using Exceptions for Normal Control Flow

Prefer if for expected cases; exceptions for exceptional cases.

What’s Next

Multithreading.

FAQ

What is stack trace?

Print with e.printStackTrace() or logger—shows where failure originated.

Should I create many custom exceptions?

Start with standard types; add custom ones when callers need specific handling.

Difference between throw and throws?

throw raises an exception; throws declares that a method may propagate checked exceptions.

Does finally run if return in try?

Yes, finally runs before the method actually returns (with nuances around exceptions in finally—avoid throwing there).

Wrap Integer.parseInt and file I/O in try-catch for user-friendly messages.