Exception Handling
Learn how to handle exceptions gracefully using try-catch blocks. Understand different exception types and best practices for error handling.
Java Exceptions: Throwing and Custom Exceptions
Understanding Exception Throwing
Exceptions in Java are a way to handle errors and unexpected situations that occur during program execution. When an error occurs, an exception object is created and thrown. This process signals that something abnormal has happened and that normal execution cannot continue. The exception then needs to be caught and handled appropriately, or the program will terminate.
Throwing an exception interrupts the normal flow of the program. Instead of continuing to the next line of code, the Java runtime system searches for an appropriate exception handler (a catch
block) to deal with the exception. If no suitable handler is found, the program will terminate with an error message.
Exceptions provide a structured mechanism for handling errors, improving code robustness and maintainability. They allow you to separate error-handling logic from the main program logic, making your code cleaner and easier to understand.
Explicitly Throwing Exceptions with the throw
Keyword
In Java, you can explicitly throw exceptions using the throw
keyword. This allows you to signal an error condition from within your code, even if the error doesn't arise directly from a Java runtime problem. You typically throw an exception when a specific condition isn't met or when a function receives invalid input.
The syntax for throwing an exception is: throw new ExceptionType("Error message");
Where:
throw
is the keyword used to throw the exception.new ExceptionType("Error message")
creates a new exception object of the specified type, with an optional error message. Common exception types includeIllegalArgumentException
,NullPointerException
, andIOException
. You can also throw custom exceptions, as we'll see later.
Example: Throwing an IllegalArgumentException
public class ExampleThrow {
public static int divide(int numerator, int denominator) {
if (denominator == 0) {
throw new IllegalArgumentException("Denominator cannot be zero.");
}
return numerator / denominator;
}
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("Result: " + result); // This line won't be reached if an exception is thrown
} catch (IllegalArgumentException e) {
System.err.println("Error: " + e.getMessage());
}
}
}
In this example, the divide
method checks if the denominator is zero. If it is, an IllegalArgumentException
is thrown with a descriptive error message. The main
method catches this exception and prints the error message to the console.
Creating and Throwing Custom Exceptions
Java allows you to create your own custom exception classes. This is useful for representing specific error conditions that are relevant to your application. Custom exceptions can make your code more readable and easier to debug.
To create a custom exception, you create a new class that extends the Exception
class (or one of its subclasses, like RuntimeException
). It's common to provide constructors that allow you to set a custom error message.
Example: Creating a Custom InsufficientFundsException
// Custom exception class
class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}
class BankAccount {
private double balance;
public BankAccount(double initialBalance) {
this.balance = initialBalance;
}
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Insufficient funds: Balance is " + balance + ", but you tried to withdraw " + amount);
}
balance -= amount;
System.out.println("Withdrawal successful. New balance: " + balance);
}
public static void main(String[] args) {
BankAccount account = new BankAccount(100.0);
try {
account.withdraw(150.0);
} catch (InsufficientFundsException e) {
System.err.println("Transaction failed: " + e.getMessage());
}
}
}
In this example:
InsufficientFundsException
extendsException
. This makes it a checked exception, meaning the compiler will force callers of methods that throw it to either catch it or declare that they also throw it.- The
BankAccount
class has awithdraw
method that throws anInsufficientFundsException
if the withdrawal amount exceeds the account balance. - The
main
method attempts to withdraw an amount that exceeds the balance and catches theInsufficientFundsException
.
Choosing between checked (extending `Exception`) and unchecked (extending `RuntimeException`) exceptions depends on the nature of the error. Checked exceptions represent exceptional conditions that a well-written application should anticipate and recover from. Unchecked exceptions, on the other hand, represent programming errors or situations that are generally unrecoverable.