In Java, custom exceptions are user-defined exceptions that extend the built-in Exception
or RuntimeException
classes. They allow you to represent specific error conditions that are meaningful to your application domain, improving code clarity, maintainability, and robustness.
Why Create Custom Exceptions?
-
Domain-Specific Clarity: Standard exceptions like
IOException
orNullPointerException
may not describe application-specific issues precisely. Custom exceptions provide meaningful names likeInsufficientFundsException
orInvalidAccountNumberException
. -
Improved Error Handling: They help in categorizing and handling errors based on your application’s logic rather than relying only on generic exceptions.
-
Encapsulation of Additional Data: You can add extra fields to your custom exception classes to store useful information (e.g., error codes, context).
Steps to Create a Custom Exception
-
Extend Exception or RuntimeException:
-
Use
Exception
if you want a checked exception. -
Use
RuntimeException
for unchecked exceptions.
-
-
Provide Constructors:
-
Default constructor.
-
Constructor with an error message.
-
Optional constructor with a cause (another exception).
-
-
(Optional) Add Additional Fields:
-
To provide more context (like error codes).
-
1. Syntax for Checked Custom Exception
// Define the custom checked exception
class MyCheckedException extends Exception {
// Default constructor
public MyCheckedException() {
super();
}
// Constructor with custom message
public MyCheckedException(String message) {
super(message);
}
// Constructor with message and cause
public MyCheckedException(String message, Throwable cause) {
super(message, cause);
}
}
Code language: JavaScript (javascript)
2. Syntax for Unchecked Custom Exception
// Define the custom unchecked exception
class MyUncheckedException extends RuntimeException {
// Default constructor
public MyUncheckedException() {
super();
}
// Constructor with custom message
public MyUncheckedException(String message) {
super(message);
}
// Constructor with message and cause
public MyUncheckedException(String message, Throwable cause) {
super(message, cause);
}
}
Code language: JavaScript (javascript)
Program 1: Checked Custom Exception
Program Statement: Create a checked custom exception InvalidAgeException
. If the age provided is below 18, throw the exception. Otherwise, print a welcome message.
// Custom checked exception class InvalidAgeException extends Exception { public InvalidAgeException(String message) { super(message); } } public class CheckedExceptionDemo { public static void validateAge(int age) throws InvalidAgeException { if (age < 18) { throw new InvalidAgeException("Age must be 18 or above to vote."); } else { System.out.println("Welcome! You are eligible to vote."); } } public static void main(String[] args) { try { validateAge(16); // Change this to 20 to see valid output } catch (InvalidAgeException e) { System.out.println("Caught Exception: " + e.getMessage()); } } } /* Caught Exception: Age must be 18 or above to vote. */
Program 2: Unchecked Custom Exception
Program Statement: Create an unchecked custom exception EmptyStringException
. If the string passed is null or empty, throw the exception. Otherwise, print the string in uppercase.
// Custom unchecked exception class EmptyStringException extends RuntimeException { public EmptyStringException(String message) { super(message); } } public class UncheckedExceptionDemo { public static void printUpperCase(String text) { if (text == null || text.trim().isEmpty()) { throw new EmptyStringException("Input string cannot be null or empty."); } else { System.out.println("Uppercase: " + text.toUpperCase()); } } public static void main(String[] args) { try { printUpperCase(""); // Change this to "hello" to see valid output } catch (EmptyStringException e) { System.out.println("Caught Exception: " + e.getMessage()); } } } /* Caught Exception: Input string cannot be null or empty. */
Custom Exceptions with Error Codes in Java
In real-world applications, especially in enterprise and distributed systems, it is often helpful to associate error codes with exceptions. This provides an easy way to identify and categorize different types of errors programmatically, enabling better error handling, logging, debugging, and even user feedback mechanisms.
Program Statement
Design a banking system where users can withdraw money from their account. If the user provides an invalid account number, tries to withdraw more money than the balance, or attempts an unauthorized operation, throw a custom exception with an appropriate error code and message.
// Custom exception class with error code class BankingException extends Exception { private final int errorCode; public BankingException(String message, int errorCode) { super(message); this.errorCode = errorCode; } public int getErrorCode() { return errorCode; } } // Account class simulating a simple bank account class Account { private String accountNumber; private double balance; private boolean isAuthorized; public Account(String accountNumber, double balance, boolean isAuthorized) { this.accountNumber = accountNumber; this.balance = balance; this.isAuthorized = isAuthorized; } public void withdraw(String inputAccountNumber, double amount) throws BankingException { if (!this.accountNumber.equals(inputAccountNumber)) { throw new BankingException("Invalid account number.", 1001); } if (!isAuthorized) { throw new BankingException("Unauthorized access attempt.", 1003); } if (amount > balance) { throw new BankingException("Insufficient balance.", 1002); } balance -= amount; System.out.println("Withdrawal successful. Remaining balance: $" + balance); } } // Main class to test the program public class BankApp { public static void main(String[] args) { // Creating an authorized account with $500 balance Account acc = new Account("ABC123", 500.0, true); try { acc.withdraw("ABC123", 100.0); // Successful case acc.withdraw("XYZ999", 50.0); // Invalid account number } catch (BankingException e) { System.out.println("Error Code: " + e.getErrorCode()); System.out.println("Error Message: " + e.getMessage()); } try { acc.withdraw("ABC123", 1000.0); // Insufficient balance } catch (BankingException e) { System.out.println("Error Code: " + e.getErrorCode()); System.out.println("Error Message: " + e.getMessage()); } // Simulate unauthorized user Account unauthorizedAcc = new Account("DEF456", 300.0, false); try { unauthorizedAcc.withdraw("DEF456", 50.0); // Unauthorized access } catch (BankingException e) { System.out.println("Error Code: " + e.getErrorCode()); System.out.println("Error Message: " + e.getMessage()); } } } /* Withdrawal successful. Remaining balance: $400.0 Error Code: 1001 Error Message: Invalid account number. Error Code: 1002 Error Message: Insufficient balance. Error Code: 1003 Error Message: Unauthorized access attempt. */