Java Exception Handling

Handle runtime errors gracefully using try-catch blocks, throw, throws, and custom exceptions.

Exception Handling in Java allows applications to gracefully handle runtime errors and continue execution without crashing.

1. Try and Catch

The try block encloses code that may throw an exception. The catch block handles it.

public class TryCatchDemo {
    public static void main(String[] args) {
        try {
            int[] arr = {10, 20, 30};
            System.out.println(arr[5]); // Causes ArrayIndexOutOfBoundsException
        } catch (Exception e) {
            System.out.println("Error occurred: " + e.getMessage());
        }
    }
}

2. Finally Block

The finally block executes whether an exception occurs or not. Useful for closing files, database connections, or releasing resources.

public class FinallyDemo {
    public static void main(String[] args) {
        try {
            System.out.println("Inside try block");
            int divide = 10 / 0; // Throws error
        } catch (Exception e) {
            System.out.println("Caught: " + e.getMessage());
        } finally {
            System.out.println("Finally always executes");
        }
    }
}

3. The throw Keyword

The throw keyword is used to manually throw an exception.

public class ThrowDemo {

    static void checkAge(int age) {
        if (age < 18) {
            throw new IllegalArgumentException("Access denied – You must be at least 18.");
        } else {
            System.out.println("Access granted");
        }
    }

    public static void main(String[] args) {
        checkAge(15);
    }
}

4. The throws Keyword

The throws keyword declares that a method may throw an exception. The calling method must handle it.

import java.io.IOException;

public class ThrowsDemo {

    static void readData() throws IOException {
        throw new IOException("Unable to read data");
    }

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

5. Checked vs Unchecked Exceptions

Checked Exceptions: Occur at compile-time (e.g., IOException, SQLException).

Unchecked Exceptions: Occur at runtime (e.g., NullPointerException, ArithmeticException).

6. Creating a Custom Exception

class InvalidAgeException extends Exception {
    public InvalidAgeException(String message) {
        super(message);
    }
}

public class CustomExceptionDemo {

    static void validate(int age) throws InvalidAgeException {
        if (age < 18) {
            throw new InvalidAgeException("Custom Error: Age must be 18 or above");
        }
        System.out.println("Valid Age!");
    }

    public static void main(String[] args) {
        try {
            validate(15);
        } catch (InvalidAgeException e) {
            System.out.println(e.getMessage());
        }
    }
}

7. Multiple Catch Blocks

Java allows multiple catch blocks to handle different exception types separately. This improves clarity and enables precise error handling.

Try example:

public class MultipleCatchDemo {
    public static void main(String[] args) {
        try {
            int[] arr = new int[3];
            System.out.println(arr[5]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Array index issue");
        } catch (Exception e) {
            System.out.println("General exception occurred");
        }
    }
}

Always catch specific exceptions before general ones like Exception, otherwise the compiler will throw an error.

8. Exception Hierarchy in Java

All exceptions in Java follow a well-defined hierarchy. At the top is the Throwable class.

  • Error – Serious system-level issues (OutOfMemoryError)
  • Exception – Recoverable conditions
  • RuntimeException – Unchecked exceptions

Understanding this hierarchy helps in deciding whether to catch, throw, or ignore certain exceptions.

9. Try-with-Resources Statement

Introduced in Java 7, try-with-resources automatically closes resources such as files and streams, reducing memory leaks.

Try example:

import java.io.FileReader;
import java.io.IOException;

public class TryWithResourcesDemo {
    public static void main(String[] args) {
        try (FileReader reader = new FileReader("data.txt")) {
            System.out.println("File opened successfully");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
}

This approach is preferred over manually closing resources inside finally.

10. Real-Life Use Cases of Exception Handling

Exception handling is widely used in real-world applications:

  • Validating user input in web forms
  • Handling failed database connections
  • Managing file upload and download errors
  • Preventing application crashes in production

Well-handled exceptions improve application stability and user experience.

11. Common Mistakes in Exception Handling

  • Catching Exception everywhere
  • Ignoring exceptions without logging
  • Using exceptions for normal flow control
  • Swallowing exceptions in empty catch blocks

Proper exception handling makes debugging easier and prevents hidden bugs.

12. Frequently Asked Interview Questions

  • Can we have try without catch?
  • What happens if finally throws an exception?
  • Difference between checked and unchecked exceptions?
  • Why RuntimeException is unchecked?

These questions are commonly asked in Java interviews and exams.