Syllabus / Java / Phase 4: Collections & Error Handling (Days 17–21)
Advanced

Custom Exceptions and Real-World Error Handling

📂 Phase 4: Collections & Error Handling (Days 17–21) · Java

Java's built-in exceptions don't always describe your application's specific business rules. Custom exceptions let your error messages and types match the actual problem domain.

Creating a Custom Exception

// Custom checked exception
public class InsufficientFundsException extends Exception {
    public InsufficientFundsException(String message) {
        super(message);
    }
}

Using It in Real Code

public class BankAccount {
    private double balance;

    public void withdraw(double amount) throws InsufficientFundsException {
        if (amount > balance) {
            throw new InsufficientFundsException(
                "Cannot withdraw " + amount + ", balance is only " + balance
            );
        }
        balance -= amount;
    }
}

public class Main {
    public static void main(String[] args) {
        BankAccount acc = new BankAccount();
        try {
            acc.withdraw(5000);
        } catch (InsufficientFundsException e) {
            System.out.println("Transaction failed: " + e.getMessage());
        }
    }
}

Checked vs Unchecked Custom Exceptions

// Checked — extends Exception, caller MUST handle or declare it
class InvalidAgeException extends Exception {
    public InvalidAgeException(String msg) { super(msg); }
}

// Unchecked — extends RuntimeException, handling is optional
class InvalidAgeRuntimeException extends RuntimeException {
    public InvalidAgeRuntimeException(String msg) { super(msg); }
}

Exception Chaining

Sometimes you want to wrap a low-level exception inside a more meaningful one without losing the original cause:

try {
    // some database operation
} catch (SQLException e) {
    throw new RuntimeException("Failed to save user record", e); // original cause preserved
}

Best Practices for Real Applications

  • Never catch Exception broadly and silently swallow it — at minimum, log it
  • Use specific exception types so calling code can react appropriately to each failure mode
  • Keep exception messages clear enough to debug from logs alone, without needing to reproduce the bug
  • Don't use exceptions for normal control flow (e.g., don't throw an exception just to break out of a loop)
Interview tip: "When should you create a custom exception instead of using a built-in one?" — When the built-in exception types don't clearly communicate WHY the failure happened in terms of your application's business logic. A generic RuntimeException tells a developer nothing; InsufficientFundsException tells them everything.