Custom Exceptions
Part of the Object Oriented Programming section of Coddy's Java journey — lesson 60 of 87.
Java's built-in exceptions cover many common error scenarios, but sometimes you need exceptions that are specific to your application's domain. Custom exceptions let you create meaningful error types that clearly communicate what went wrong.
To create a custom exception, simply extend an existing exception class. For a checked exception, extend Exception:
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}For an unchecked exception, extend RuntimeException:
public class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);
}
}The super(message) call passes the error message to the parent class, making it available through getMessage(). You can then throw and catch your custom exception like any other:
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Balance too low: " + balance);
}
balance -= amount;
}
// Using it
try {
account.withdraw(1000);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}Custom exceptions make your code more readable and allow callers to handle specific error conditions differently. They're especially valuable when building APIs or libraries where clear error communication matters.
Challenge
EasyLet's build a ticket booking system that uses custom exceptions to handle different error scenarios! You'll create meaningful exception types that clearly communicate what went wrong when booking tickets.
You'll organize your code across four files:
TicketSoldOutException.java: Create a custom checked exception (extendsException) for when tickets are no longer available. Your exception should accept a message in its constructor and pass it to the parent class usingsuper(message).InvalidSeatException.java: Create a custom unchecked exception (extendsRuntimeException) for when someone tries to book an invalid seat number. This exception should also accept and pass a message to its parent.TicketBooth.java: Create a class that manages ticket sales. Your booth should track the total number of available seats and the highest valid seat number. Include:A constructor that takes the total number of seats available.
A
bookTicket(int seatNumber)method that validates the booking. If no tickets remain (available seats is 0 or less), throw aTicketSoldOutExceptionwith the message"No tickets remaining". If the seat number is less than 1 or greater than the total seats, throw anInvalidSeatExceptionwith the message"Seat [seatNumber] does not exist". Otherwise, decrease available seats by 1 and printBooked seat [seatNumber] successfully.A
getAvailableSeats()method that returns the current count of available seats.Main.java: Bring your ticket system together! You'll receive two inputs: the total number of seats and a seat number to book.Create a
TicketBoothwith the given total seats. Then attempt to book the specified seat number inside a try-catch block. SinceTicketSoldOutExceptionis checked, you must handle it. CatchTicketSoldOutExceptionfirst and printBooking failed: [exception message]. Then catchInvalidSeatExceptionand print the same format:Booking failed: [exception message].After the try-catch block, print
Remaining seats: [count]using the getter method.
You will receive two inputs in order: total seats (integer) and seat number to book (integer).
Notice how checked exceptions force callers to handle them (with try-catch or throws), while unchecked exceptions don't require explicit handling. Choose the exception type based on whether the error is something callers should anticipate and recover from!
Cheat sheet
To create a custom exception, extend an existing exception class.
For a checked exception, extend Exception:
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}For an unchecked exception, extend RuntimeException:
public class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);
}
}The super(message) call passes the error message to the parent class, making it available through getMessage().
Throw and catch custom exceptions like any other exception:
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Balance too low: " + balance);
}
balance -= amount;
}
// Using it
try {
account.withdraw(1000);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}Checked exceptions force callers to handle them with try-catch or throws. Unchecked exceptions don't require explicit handling. Choose based on whether the error is something callers should anticipate and recover from.
Try it yourself
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int totalSeats = scanner.nextInt();
int seatNumber = scanner.nextInt();
// TODO: Create a TicketBooth with the given total seats
// TODO: Use a try-catch block to attempt booking the seat
// - Catch TicketSoldOutException first and print "Booking failed: [exception message]"
// - Catch InvalidSeatException and print "Booking failed: [exception message]"
// TODO: After the try-catch, print "Remaining seats: [count]"
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting10Exception Handling in OOP
Exception Class HierarchyCustom ExceptionsChecked vs Unchecked ErrorsTry With Resources PatternRecap - Validated User2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System