Exception handling in Java is a powerful mechanism that handles runtime errors, ensuring the normal flow of the program. This tutorial will cover the basics of exception handling, including types of exceptions, try-catch blocks, finally blocks, and custom exceptions.

Key Concepts

  1. Exception Hierarchy
  2. Try-Catch Block
  3. Finally Block
  4. Throw and Throws
  5. Custom Exceptions

1. Exception Hierarchy

In Java, all exceptions are represented by classes that are part of the java.lang package. The root class of the exception hierarchy is Throwable.

  • Checked Exceptions: These are checked at compile-time (e.g., IOException, SQLException).
  • Unchecked Exceptions: These are checked at runtime (e.g., ArithmeticException, NullPointerException).
  • Errors: These are serious problems that a reasonable application should not try to catch (e.g., OutOfMemoryError, StackOverflowError).

2. Try-Catch Block

The try block contains the code that might throw an exception, and the catch block contains the code to handle the exception.

  public class Main {
    public static void main(String[] args) {
        try {
            int divideByZero = 5 / 0;
        } catch (ArithmeticException e) {
            System.out.println("ArithmeticException: Cannot divide by zero.");
        }
    }
}
  

3. Finally Block

The finally block contains the code that will always be executed, regardless of whether an exception is thrown or not.

  public class Main {
    public static void main(String[] args) {
        try {
            int[] numbers = {1, 2, 3};
            System.out.println(numbers[10]);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("ArrayIndexOutOfBoundsException: Index out of bounds.");
        } finally {
            System.out.println("This will always be executed.");
        }
    }
}
  

4. Throw and Throws

The throw keyword is used to explicitly throw an exception, while throws is used in method signatures to declare that a method can throw an exception.

  // Using throw
public class Main {
    public static void validateAge(int age) {
        if (age < 18) {
            throw new IllegalArgumentException("Age must be 18 or above.");
        }
    }

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

// Using throws
import java.io.IOException;

public class Main {
    public static void readFile() throws IOException {
        throw new IOException("File not found");
    }

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

5. Custom Exceptions

You can create your own exceptions by extending the Exception class.

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

public class Main {
    public static void checkNumber(int number) throws CustomException {
        if (number < 0) {
            throw new CustomException("Number cannot be negative.");
        }
    }

    public static void main(String[] args) {
        try {
            checkNumber(-5);
        } catch (CustomException e) {
            System.out.println("CustomException: " + e.getMessage());
        }
    }
}