Java Tutorial
🔍
Java ProgramsExceptionsCustom Exception

Custom Exception in Java

intermediate·  Exceptions  ·  Error Handling

Problem

A custom exception is a user-defined class that extends Exception (or RuntimeException) to represent a specific error condition in your own code.

Define a custom exception and throw it when a withdrawal exceeds the account balance.

Input
balance=100, withdraw=150
Output
Error: Insufficient funds for this withdrawal

Java Program

Java
class InsufficientFundsException extends Exception { InsufficientFundsException(String message) { super(message); // forwards the message so getMessage() can return it } } public class BankAccount { // throws clause forces callers to catch or declare this checked exception static void withdraw(double balance, double amount) throws InsufficientFundsException { if (amount > balance) { throw new InsufficientFundsException("Insufficient funds for this withdrawal"); } System.out.println("Withdrawal successful"); } public static void main(String[] args) { try { withdraw(100.0, 150.0); } catch (InsufficientFundsException e) { System.out.println("Error: " + e.getMessage()); } } }

Output

Error: Insufficient funds for this withdrawal

Core Logic

Sometimes the built-in exceptions don't fit — here a custom checked exception is thrown when a withdrawal breaks the balance rule.

How It Works
  1. 1class InsufficientFundsException extends Exception creates a new checked exception type.
  2. 2Its constructor forwards the message to super(message), so getMessage() returns it later.
  3. 3withdraw() declares throws InsufficientFundsException, requiring callers to handle it.
  4. 4When amount > balance, the method does throw new InsufficientFundsException(...) instead of continuing.
  5. 5The caller wraps the call in try/catch and reads the message back with e.getMessage().
Withdrawing 150 from a balance of 100 throws the custom exception, caught and printed as "Error: Insufficient funds for this withdrawal".
💡

Key Point: Extending Exception (not RuntimeException) makes this a checked exception — the compiler forces every caller to either catch it or declare it.

Key Concepts

custom exceptionextends Exceptionthrows

Approach 2: Unchecked Custom Exception

Java
class InsufficientFundsRuntimeException extends RuntimeException { InsufficientFundsRuntimeException(String message) { super(message); } } public class BankAccountUnchecked { // No throws clause needed — RuntimeException is unchecked static void withdraw(double balance, double amount) { if (amount > balance) { throw new InsufficientFundsRuntimeException("Insufficient funds for this withdrawal"); } System.out.println("Withdrawal successful"); } public static void main(String[] args) { try { withdraw(100.0, 150.0); } catch (InsufficientFundsRuntimeException e) { System.out.println("Error: " + e.getMessage()); } } }

Output

Error: Insufficient funds for this withdrawal

Core Logic

The same idea works as an unchecked exception too — extend RuntimeException instead, and callers are no longer forced to handle it.

How It Works
  1. 1class InsufficientFundsRuntimeException extends RuntimeException makes this an unchecked exception.
  2. 2withdraw() no longer needs a throws clause — the compiler doesn't require callers to catch or declare unchecked exceptions.
  3. 3The throw statement inside withdraw() is otherwise identical to the checked version.
  4. 4The caller still chooses to wrap the call in try/catch here, but it's now optional rather than compiler-enforced.
Calling withdraw(100.0, 150.0) throws the same way as before, but the compiler would have allowed calling it with no try/catch at all.
💡

Key Point: Use a checked exception when callers can reasonably be expected to recover (like retrying with a smaller amount); use an unchecked one when the failure represents a programming error or a business rule violation the caller isn't expected to routinely handle.

Key Concepts

RuntimeExceptionunchecked exceptionchecked vs. unchecked

Related Programs