# Custom Exceptions & Multi-Catch — Core Java

Source: https://www.geekswithgeeks.com/en/core-java/java-exceptions-deep-dive

> Design your own exception types that carry meaningful context, and handle several exception types in one concise catch clause.

## A custom checked exception

Extend `Exception` for a checked exception callers must handle, or `RuntimeException` for an unchecked one signalling a programming error. Always chain the original cause so the stack trace stays complete.

```java
public class InsufficientFundsException extends Exception {
    private final double shortfall;

    public InsufficientFundsException(double shortfall) {
        super("short by " + shortfall);
        this.shortfall = shortfall;
    }
    public double getShortfall() { return shortfall; }
}

// caller:
void withdraw(double amt) throws InsufficientFundsException {
    if (amt > balance) throw new InsufficientFundsException(amt - balance);
    balance -= amt;
}
```

## Multi-catch

When two exception types need the **same** handling, catch both with `|` instead of duplicating the block. The caught variable is effectively final and typed as the common supertype.

```java
try {
    process(file);
} catch (IOException | ParseException e) {
    log.error("could not process file", e);
    throw new RuntimeException(e);
}
```

## Rethrow with context, don't hide it

Catching a low-level exception just to throw a more meaningful one is good practice — **as long as you pass the original as the cause** (`new ServiceException("...", e)`), never dropping it, or the real root cause becomes invisible in production logs.

Quick check

**Quiz:** Which base class should a custom exception extend if callers should NOT be forced to declare or catch it?

- [ ] Exception
- [ ] Throwable
- [x] RuntimeException
- [ ] Error

*Answer:* RuntimeException. RuntimeException (and its subclasses) are unchecked — the compiler does not require a throws declaration or a catch block.
