Advanced Java ProgrammingUnit 711 min read
Exception Handling: Try-Catch, Throw, Custom Exceptions, and Best Practices
Unit 7 of Advanced Java Programming covers exception handling mechanisms in Java, including checked vs. unchecked exceptions, the try-catch-finally block, custom exceptions, and best practices for robust error handling. This note explains how exceptions disrupt normal flow, how to handle them gracefully, and how to des
TAKEAWAYS:
- Exceptions are objects that represent errors or unexpected events in Java, categorized as checked (compile-time) or unchecked (runtime).
- Use
try-catch-finallyblocks to handle exceptions gracefully, ensuring resources are released even if an error occurs. - Custom exceptions extend
ExceptionorRuntimeExceptionand allow you to define application-specific error conditions. - The
throwskeyword declares exceptions that a method might throw, whilethrowexplicitly throws an exception. - Best practices include logging exceptions, avoiding empty catch blocks, and using exceptions for exceptional cases, not control flow.
- Java provides built-in exception classes like
ArithmeticException,NullPointerException, andIOExceptionfor common error scenarios.
1. Introduction to Exceptions
Exceptions are objects that represent errors or unexpected events during program execution. They disrupt the normal flow of a program and must be handled to prevent crashes. Java exceptions are categorized into two types:
1.1 Types of Exceptions
| Type | Description | Example Classes |
|---|---|---|
| Checked Exceptions | Must be handled at compile time (checked by the compiler). | IOException, SQLException |
| Unchecked Exceptions | Occur at runtime and are not checked by the compiler (e.g., logical errors). | NullPointerException, ArrayIndexOutOfBoundsException |
| Errors | Serious system-level issues (e.g., JVM crashes). Not meant to be caught. | OutOfMemoryError, StackOverflowError |
Why handle exceptions?
- Prevents program crashes.
- Provides meaningful error messages to users.
- Ensures resources (e.g., file handles, database connections) are released properly.
2. Exception Handling Mechanism
Java uses try-catch-finally blocks to handle exceptions.
2.1 Basic Syntax
try {
// Code that may throw an exception
} catch (ExceptionType e) {
// Handle the exception
} finally {
// Always executes (e.g., cleanup)
}
2.2 Example: Handling ArithmeticException
public class ExceptionDemo {
public static void main(String[] args) {
try {
int result = 10 / 0; // Throws ArithmeticException
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero: " + e.getMessage());
} finally {
System.out.println("This always executes.");
}
}
}
Output:
Cannot divide by zero: / by zero
This always executes.
TRACE TABLE:
| Step | Code Executed | Exception Thrown? | Output |
|---|---|---|---|
| 1 | int result = 10 / 0; |
Yes (ArithmeticException) |
- |
| 2 | catch block executes |
No | "Cannot divide by zero: / by zero" |
| 3 | finally block executes |
No | "This always executes." |
3. The throws and throw Keywords
throws: Declares exceptions a method might throw (used in method signature).throw: Explicitly throws an exception (used inside a method).
3.1 Example: throws in Method Signature
import java.io.*;
public class FileReaderDemo {
public static void readFile(String path) throws IOException {
FileReader file = new FileReader(path); // May throw IOException
}
public static void main(String[] args) {
try {
readFile("nonexistent.txt");
} catch (IOException e) {
System.out.println("File not found: " + e.getMessage());
}
}
}
3.2 Example: throw Keyword
public class AgeValidator {
public static void validateAge(int age) {
if (age < 18) {
throw new ArithmeticException("Age must be 18 or above.");
}
System.out.println("Age is valid.");
}
public static void main(String[] args) {
try {
validateAge(15);
} catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Output:
Error: Age must be 18 or above.
4. Custom Exceptions
Custom exceptions extend Exception (checked) or RuntimeException (unchecked).
4.1 Example: Custom Exception for Insufficient Balance
class InsufficientBalanceException extends Exception {
public InsufficientBalanceException(String message) {
super(message);
}
}
public class BankAccount {
private double balance;
public void withdraw(double amount) throws InsufficientBalanceException {
if (amount > balance) {
throw new InsufficientBalanceException("Insufficient balance. Current balance: " + balance);
}
balance -= amount;
System.out.println("Withdrawn: " + amount);
}
public static void main(String[] args) {
BankAccount account = new BankAccount();
account.balance = 500;
try {
account.withdraw(600);
} catch (InsufficientBalanceException e) {
System.out.println("Transaction failed: " + e.getMessage());
}
}
}
Output:
Transaction failed: Insufficient balance. Current balance: 500.0
REAL WORLD:
- eSewa (Nepal): Uses custom exceptions to handle payment failures (e.g.,
InsufficientFundsExceptionwhen a user tries to pay more than their account balance). - Khalti (Nepal): Throws
TransactionTimeoutExceptionif a payment does not complete within the expected time. - Ncell (Nepal): Validates SIM card PINs and throws
InvalidPINExceptionif the user enters the wrong PIN too many times.
5. Best Practices for Exception Handling
- Catch specific exceptions: Avoid catching generic
Exceptionunless necessary.// Bad: Catches all exceptions catch (Exception e) { ... } // Good: Catch specific exceptions catch (FileNotFoundException e) { ... } catch (IOException e) { ... } - Avoid empty catch blocks: At least log the exception.
catch (Exception e) { System.err.println("Error: " + e.getMessage()); } - Use exceptions for exceptional cases: Do not use them for control flow (e.g., loop termination).
- Clean up resources in
finally: Ensure file handles, database connections, etc., are closed. - Document exceptions: Use
@throwsin JavaDoc to specify exceptions a method might throw.
6. Common Built-in Exceptions
| Exception | Cause | Example Scenario |
|---|---|---|
NullPointerException |
Accessing a null object reference. | String s = null; System.out.println(s.length()); |
ArrayIndexOutOfBoundsException |
Accessing an invalid array index. | int[] arr = {1, 2}; System.out.println(arr[2]); |
IOException |
File or network I/O errors. | FileReader file = new FileReader("nonexistent.txt"); |
NumberFormatException |
Invalid number format (e.g., parsing). | int num = Integer.parseInt("abc"); |
ClassNotFoundException |
Class not found during runtime. | Class.forName("NonexistentClass"); |
7. Exception Handling in Real-World Scenarios
Example 1: Daraz Order Processing
Daraz uses exception handling to manage failed orders:
- If a payment fails, it throws
PaymentFailedException. - If stock is unavailable, it throws
OutOfStockException. - The system logs these exceptions and notifies the user.
Mermaid Diagram: Daraz Order Flow
flowchart TD
A["User places order"] --> B["Check stock"]
B -->|"Stock available"| C["Process payment"]
C -->|"Payment succeeds"| D["Ship order"]
C -->|"Payment fails"| E["Throw PaymentFailedException"]
B -->|"Stock unavailable"| F["Throw OutOfStockException"]
E --> G["Notify user"]
F --> GExample 2: NEPSE Stock Market
NEPSE uses exception handling to manage invalid trades:
- If a user enters an invalid stock code, it throws
InvalidStockCodeException. - If the user’s balance is insufficient, it throws
InsufficientFundsException.
Code Example: NEPSE Trade Validation
class InvalidStockCodeException extends Exception {
public InvalidStockCodeException(String message) {
super(message);
}
}
public class StockTrader {
public static void buyStock(String code, double quantity) throws InvalidStockCodeException {
if (!isValidStockCode(code)) {
throw new InvalidStockCodeException("Invalid stock code: " + code);
}
System.out.println("Stock purchased: " + code + ", Quantity: " + quantity);
}
private static boolean isValidStockCode(String code) {
return code.matches("[A-Z]{3,4}");
}
public static void main(String[] args) {
try {
buyStock("ABC", 10);
buyStock("XYZ1", 5); // Invalid code
} catch (InvalidStockCodeException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Output:
Stock purchased: ABC, Quantity: 10.0
Error: Invalid stock code: XYZ1
8. Exam Tip
- For short-answer questions: Define exceptions,
try-catch,throws, andthrowclearly. Use simple examples like division by zero or array index errors. - For coding questions:
- Always include
try-catchblocks where exceptions are expected. - Use custom exceptions when designing class hierarchies (e.g.,
BankAccountwithInsufficientBalanceException). - Document exceptions using
@throwsin method comments.
- Always include
- Common pitfalls:
- Forgetting to handle checked exceptions (compile-time errors).
- Swallowing exceptions without logging or handling them.
- Using exceptions for control flow (e.g., looping).
Past Exam Question Answer Example:
Q: Describe exception handling with an example.
A:
Exception handling in Java is done using try-catch-finally blocks. When an exception occurs, the normal flow is interrupted, and the catch block executes to handle it. For example:
try {
int[] arr = {1, 2, 3};
System.out.println(arr[5]); // Throws ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Error: Index out of bounds.");
} finally {
System.out.println("Execution complete.");
}
Output:
Error: Index out of bounds.
Execution complete.
This demonstrates how exceptions are caught and handled gracefully. Custom exceptions can also be created by extending Exception or RuntimeException.
Based on the TU BIT syllabus for Advanced Java Programming (BIT401), unit 7.
Discussion
Loading…