Custom Exceptions
Overview
Java provides dozens of built-in exceptions like `NullPointerException` or `IOException`. However, in enterprise applications, business logic fails for domain-specific reasons. 'InsufficientFundsException' or 'UserNotFoundException' provide massively more clarity to your logs and debugging process than a generic 'Exception'. Creating custom exceptions allows you to map your company's business rules directly into the language's error system.
Syntax
To create a custom exception, simply create a new class that extends either `Exception` (for Checked) or `RuntimeException` (for Unchecked). Always provide a constructor that takes a String message.
// 1. Extend RuntimeException for Unchecked (Don't force callers to catch)
public class InsufficientFundsException extends RuntimeException {
private double currentBalance;
private double attemptedWithdrawal;
// Provide a detailed constructor
public InsufficientFundsException(String message, double balance, double amount) {
super(message); // Pass message to parent class
this.currentBalance = balance;
this.attemptedWithdrawal = amount;
}
public double getShortfall() {
return attemptedWithdrawal - currentBalance;
}
}Now, when the program crashes, the stack trace will explicitly say 'InsufficientFundsException', instantly telling the developer what the business logic violation was.
public class BankAccount {
private double balance = 100.0;
public void withdraw(double amount) {
if (amount > balance) {
// Throwing our custom exception!
throw new InsufficientFundsException(
"Cannot withdraw $" + amount, balance, amount);
}
balance -= amount;
}
}Common Pitfalls
- Creating a custom exception but forgetting to call `super(message)` inside the constructor, resulting in a blank, unhelpful stack trace.
- Creating custom Checked Exceptions (extending `Exception`) for things the user cannot possibly recover from, forcing developers to write useless boilerplate Try-Catch blocks.
Interview Tips
- When asked to design a system, mention using custom exceptions (e.g., UserNotFoundException) to map business rules directly into the error system.
Real-World Example
Global Exception Handlers in Spring Boot map custom exceptions directly to specific HTTP status codes.
// When Spring sees this exception thrown anywhere, it automatically
// returns an HTTP 404 Not Found to the client!
@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String resourceType, String id) {
super(resourceType + " with ID " + id + " was not found.");
}
}