How do you create a custom exception in Java, and what information should it carry?
A custom exception is a class that extends Exception or RuntimeException. The decision on which one is the same one you make for any exception: extend RuntimeException when the failure means the caller made a mistake, and extend Exception when it is an expected external condition the caller should handle.
The mechanics are simple. Name the class after the condition, give it serialVersionUID because Exception is Serializable, and add constructors that set a useful message and store whatever extra data the caller needs to act on the failure. The best custom exceptions carry structured data rather than only a message, because a caller that has to parse a message string to find out what went wrong is worse off than one that reads a typed field.
public class Main {
public static void main(String[] args) {
try {
withdraw(50);
} catch (InsufficientFundsException e) {
System.out.println("error : " + e.getMessage());
System.out.println("code : " + e.getCode());
System.out.println("balance : " + e.getBalance());
}
}
static void withdraw(double amount) throws InsufficientFundsException {
double balance = 20.0;
if (amount > balance) {
throw new InsufficientFundsException(amount, balance);
}
}
}
class InsufficientFundsException extends Exception {
private static final long serialVersionUID = 1L;
private final double requested;
private final double available;
InsufficientFundsException(double requested, double available) {
super("insufficient funds: asked for " + requested + ", available " + available);
this.requested = requested;
this.available = available;
}
double getRequested() {
return requested;
}
double getBalance() {
return available;
}
int getCode() {
return 4001;
}
}The output shows the point of a custom exception. The caller can display the human-readable message, but it can also read a numeric code to map to an HTTP status, and it can read the available balance to decide whether to suggest a smaller amount. None of that required parsing a string.
A few design habits that make custom exceptions pleasant to use. Give the class a name that describes the condition, not the fix, so that InsufficientFundsException is better than NotEnoughMoneyException. Provide a constructor that takes a message and one that takes structured data, and have the structured constructor build the message itself so the message and the fields can never disagree. And keep the exception immutable, exactly as you would any value object.