← Back to Java series
πŸ’Ύ
Exceptions & I/O
Exceptions & I/O Β· Prerequisite: previous lecture

15. Exception Handling

Exceptions are objects that represent **errors at runtime**. This lecture covers `try` / `catch` / `finally`, the difference between checked and unchecked exceptions, custom exceptions, and try-with-resources.

Javaexceptiontry-catchtry-with-resources
Duration
⏱ ~1.5-2 hours
Level
πŸ“Š Intermediate
Prerequisite
🎯 Previous lecture or equivalent knowledge
OUTCOME
Exceptions are objects that represent **errors at runtime**. This lecture covers `try` / `catch` / `finally`, the difference between checked and unchecked exceptions, custom exceptions, and try-with-resources.

What you'll learn

  • 1Catch and rethrow with `try` / `catch` / `finally`
  • 2Distinguish checked vs unchecked exceptions
  • 3Create custom exception classes
  • 4Auto-close resources with try-with-resources

Overview

Exceptions are objects that represent **errors at runtime**. This lecture covers `try` / `catch` / `finally`, the difference between checked and unchecked exceptions, custom exceptions, and try-with-resources.

Core Concepts

1) `try` / `catch` / `finally`

java
try {
    int x = Integer.parseInt("abc");
} catch (NumberFormatException e) {
    System.out.println("parse failed: " + e.getMessage());
} finally {
    System.out.println("always runs");
}

2) Checked vs unchecked

  • **Checked** (`IOException`, ...) β€” the compiler forces you to handle or declare with `throws`
  • **Unchecked** (`RuntimeException` and subclasses) β€” programmer errors, the compiler doesn't force handling

3) Custom exception

java
public class InsufficientBalanceException extends RuntimeException {
    public InsufficientBalanceException(String msg) { super(msg); }
}

4) `throw` / `throws`

java
static int divide(int a, int b) {
    if (b == 0) throw new IllegalArgumentException("b != 0");
    return a / b;
}

static void writeFile() throws java.io.IOException { ... }

5) try-with-resources

java
try (var br = java.nio.file.Files.newBufferedReader(java.nio.file.Path.of("a.txt"))) {
    String line = br.readLine();
}   // br.close() called automatically

Any resource implementing `AutoCloseable` works.

Examples

Example 1 β€” `BasicTryCatch.java`

java
public class BasicTryCatch {
    public static void main(String[] args) {
        try {
            int n = Integer.parseInt("abc");
            System.out.println(n);
        } catch (NumberFormatException e) {
            System.out.println("parse failed: " + e.getMessage());
        } finally {
            System.out.println("done");
        }
    }
}

**Output**

text
parse failed: For input string: "abc"
done

Example 2 β€” `MultiCatch.java`

java
public class MultiCatch {
    public static void main(String[] args) {
        try {
            riskyOp(Integer.parseInt(args.length > 0 ? args[0] : "0"));
        } catch (NumberFormatException | ArithmeticException e) {
            System.out.println("error: " + e.getClass().getSimpleName());
        }
    }
    static void riskyOp(int n) { System.out.println(10 / n); }
}

**Note:** `|` joins multiple exception types in one `catch` arm.

Example 3 β€” `CustomException.java`

java
public class CustomException {
    static class InsufficientBalanceException extends RuntimeException {
        InsufficientBalanceException(String msg) { super(msg); }
    }

    static void withdraw(long balance, long amount) {
        if (amount > balance) throw new InsufficientBalanceException("need " + amount + ", have " + balance);
    }

    public static void main(String[] args) {
        try {
            withdraw(1000, 5000);
        } catch (InsufficientBalanceException e) {
            System.out.println(e.getMessage());
        }
    }
}

**Output**

text
need 5000, have 1000

Example 4 β€” `TryWithResources.java`

java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;

public class TryWithResources {
    public static void main(String[] args) throws IOException {
        try (BufferedReader br = new BufferedReader(new StringReader("line1\nline2"))) {
            String s;
            while ((s = br.readLine()) != null) System.out.println("> " + s);
        }   // br closed automatically
    }
}

**Output**

text
> line1
> line2

Common Mistakes

  1. Catching `Exception` (or worse, `Throwable`) β€” too broad, hides bugs
  2. Empty catch blocks β†’ silent failures
  3. Catching an exception only to log and rethrow without context
  4. Forgetting to close resources without try-with-resources
  5. Throwing a checked exception from `main` without `throws` clause

Summary

  • Catch the **specific** exception, then act on it
  • Use try-with-resources for any `AutoCloseable`
  • Define custom exceptions for domain-specific errors

Practice

# Practice - 15. Exception Handling

## Exercise 1 β€” Safe division

  • File: `Homework01.java`
  • Key concepts: `try` / `catch`

Requirements

  • Define `static int safeDiv(int a, int b)` that returns -1 on `ArithmeticException`.
  • In main call `safeDiv(10, 2)` and `safeDiv(10, 0)`.

Expected output

text
5
-1

## Exercise 2 β€” `BankAccount` with custom exception

  • File: `Homework02.java`
  • Key concepts: custom exception, `throw`

Requirements

  • Class `Account` with `private long balance`.
  • `withdraw(long)` throws `InsufficientBalanceException` if amount > balance.
  • Catch and print the message in main.

Expected output

text
balance=10000
withdraw 5000 -> balance=5000
withdraw 6000 -> need 6000, have 5000

## Solutions After trying it yourself, compare with [`answer/`](./answer/).

Solution code (homework/answer/)

answer/Homework01.java

java
/** Safe division. */
public class Homework01 {
    public static void main(String[] args) {
        System.out.println(safeDiv(10, 2));
        System.out.println(safeDiv(10, 0));
    }

    static int safeDiv(int a, int b) {
        try {
            return a / b;
        } catch (ArithmeticException e) {
            return -1;
        }
    }
}

answer/Homework02.java

java
/** BankAccount with custom exception. */
public class Homework02 {
    static class InsufficientBalanceException extends RuntimeException {
        InsufficientBalanceException(String m) { super(m); }
    }

    static class Account {
        private long balance;
        Account(long b) { this.balance = b; }
        long getBalance() { return balance; }
        void withdraw(long amount) {
            if (amount > balance)
                throw new InsufficientBalanceException("need " + amount + ", have " + balance);
            balance -= amount;
        }
    }

    public static void main(String[] args) {
        Account a = new Account(10_000);
        System.out.println("balance=" + a.getBalance());
        a.withdraw(5_000);
        System.out.println("withdraw 5000 -> balance=" + a.getBalance());
        try {
            a.withdraw(6_000);
        } catch (InsufficientBalanceException e) {
            System.out.println("withdraw 6000 -> " + e.getMessage());
        }
    }
}

Try It Yourself

bash
cd 04_io/15_exception/src
javac BasicTryCatch.java
java BasicTryCatch

Next Lecture

[16_File_IO](../16_파일_μž…μΆœλ ₯/) β€” read and write with the modern NIO.2 API.

Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub β†—