Java Exception Handling

An exception is an unexpected event that occurs during the execution of a program, disrupting its normal flow. Exception handling is a mechanism that allows a program to detect and respond to these errors gracefully — instead of crashing, it can take corrective action or provide a meaningful message.

What Causes Exceptions?

  • Dividing a number by zero.
  • Trying to access an array element at an invalid index.
  • Converting an invalid string to a number.
  • Accessing a method on a null object.
  • Attempting to open a file that does not exist.

Exception Hierarchy

All exceptions in Java are subclasses of the Throwable class.

Throwable
├── Error (serious problems – not meant to be handled, e.g., OutOfMemoryError)
└── Exception
    ├── Checked Exceptions (must be handled at compile time)
    │   ├── IOException
    │   ├── SQLException
    │   └── FileNotFoundException
    └── RuntimeException (Unchecked – detected at runtime)
        ├── NullPointerException
        ├── ArrayIndexOutOfBoundsException
        ├── ArithmeticException
        └── NumberFormatException

try-catch Block

The try block contains code that might throw an exception. The catch block handles the exception if one occurs.

Syntax

try {
    // code that might throw an exception
} catch (ExceptionType e) {
    // code to handle the exception
}

Example – Division by Zero

public class ExceptionDemo {
    public static void main(String[] args) {
        try {
            int result = 10 / 0;   // throws ArithmeticException
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Error: Cannot divide by zero.");
            System.out.println("Details: " + e.getMessage());
        }

        System.out.println("Program continues after exception.");
    }
}

Output:

Error: Cannot divide by zero.
Details: / by zero
Program continues after exception.

Multiple catch Blocks

A single try block can have multiple catch blocks to handle different types of exceptions.

public class MultiCatch {
    public static void main(String[] args) {
        try {
            int[] arr = {1, 2, 3};
            System.out.println(arr[5]);    // ArrayIndexOutOfBoundsException
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Array index is out of bounds.");
        } catch (NullPointerException e) {
            System.out.println("Null pointer encountered.");
        } catch (Exception e) {
            System.out.println("General error: " + e.getMessage());
        }
    }
}

Output:

Array index is out of bounds.

Java catches the first matching exception. The more specific exception types should come before the more general ones.

The finally Block

The finally block always executes — whether or not an exception occurred. It is typically used for cleanup tasks such as closing a file, releasing a database connection, or freeing resources.

public class FinallyDemo {
    public static void main(String[] args) {
        try {
            int result = 10 / 2;
            System.out.println("Result: " + result);
        } catch (ArithmeticException e) {
            System.out.println("Division error.");
        } finally {
            System.out.println("finally block always runs.");
        }
    }
}

Output:

Result: 5
finally block always runs.

The throw Keyword

The throw keyword is used to manually throw an exception from within code. This is useful when custom validation fails.

public class AgeValidator {
    static void validateAge(int age) {
        if (age < 18) {
            throw new IllegalArgumentException("Age must be 18 or above. Got: " + age);
        }
        System.out.println("Age is valid: " + age);
    }

    public static void main(String[] args) {
        try {
            validateAge(15);
        } catch (IllegalArgumentException e) {
            System.out.println("Validation failed: " + e.getMessage());
        }
    }
}

Output:

Validation failed: Age must be 18 or above. Got: 15

The throws Keyword

The throws keyword is used in a method signature to declare that the method might throw an exception. It passes the responsibility of handling the exception to the calling method.

import java.io.IOException;

public class ThrowsDemo {

    static void readFile(String filename) throws IOException {
        if (!filename.endsWith(".txt")) {
            throw new IOException("Only .txt files are allowed.");
        }
        System.out.println("Reading: " + filename);
    }

    public static void main(String[] args) {
        try {
            readFile("data.csv");
        } catch (IOException e) {
            System.out.println("Caught: " + e.getMessage());
        }
    }
}

Output:

Caught: Only .txt files are allowed.

Checked vs Unchecked Exceptions

FeatureChecked ExceptionsUnchecked (Runtime) Exceptions
Detected atCompile timeRuntime
Must handle?Yes (or declare with throws)No (optional)
ExamplesIOException, SQLExceptionNullPointerException, ArithmeticException

Creating Custom Exceptions

Custom exceptions make error messages more meaningful and specific to the application.

class InsufficientFundsException extends Exception {
    InsufficientFundsException(String message) {
        super(message);
    }
}

class Account {
    private double balance;

    Account(double balance) {
        this.balance = balance;
    }

    void withdraw(double amount) throws InsufficientFundsException {
        if (amount > balance) {
            throw new InsufficientFundsException(
                "Cannot withdraw Rs. " + amount + ". Available: Rs. " + balance);
        }
        balance -= amount;
        System.out.println("Withdrawn: Rs. " + amount + ". Remaining: Rs. " + balance);
    }
}

public class Main {
    public static void main(String[] args) {
        Account acc = new Account(1000);

        try {
            acc.withdraw(500);
            acc.withdraw(800);   // exceeds balance
        } catch (InsufficientFundsException e) {
            System.out.println("Error: " + e.getMessage());
        }
    }
}

Output:

Withdrawn: Rs. 500.0. Remaining: Rs. 500.0
Error: Cannot withdraw Rs. 800.0. Available: Rs. 500.0

try-with-resources (Java 7+)

The try-with-resources statement automatically closes resources (like files) that implement the AutoCloseable interface, even if an exception occurs.

import java.util.Scanner;

try (Scanner sc = new Scanner(System.in)) {
    System.out.print("Enter a number: ");
    int num = sc.nextInt();
    System.out.println("You entered: " + num);
}
// sc is automatically closed after the try block

Summary

  • An exception is an error that disrupts normal program flow.
  • Use try-catch to detect and handle exceptions gracefully.
  • The finally block always runs — use it for cleanup tasks.
  • throw manually triggers an exception; throws declares a method may throw one.
  • Checked exceptions must be handled at compile time; unchecked exceptions occur at runtime.
  • Custom exceptions extend Exception and provide application-specific error messages.

Leave a Comment

Your email address will not be published. Required fields are marked *