Exception Handling

Learn how to handle exceptions gracefully using try-catch blocks. Understand different exception types and best practices for error handling.


Handling Multiple Exceptions in Java

Understanding Exception Handling

Exception handling in Java is a mechanism to handle runtime errors that may disrupt the normal flow of the program. It allows you to gracefully recover from errors and prevent your application from crashing. The try-catch block is the core of exception handling.

Handling Multiple Exceptions

Sometimes, a block of code might throw different types of exceptions. Java allows you to handle each exception type separately using multiple catch blocks. This provides more granular control over error handling and allows you to take specific actions based on the type of exception that occurred.

Multiple Catch Blocks

Here's how to handle multiple exceptions using multiple catch blocks:

 public class MultipleExceptions {
    public static void main(String[] args) {
        try {
            // Code that might throw exceptions
            int[] numbers = {1, 2, 3};
            int index = 5; // Index out of bounds
            int result = numbers[index] / 0; // ArithmeticException

            System.out.println("Result: " + result); // This line might not be reached
        } catch (ArrayIndexOutOfBoundsException e) {
            System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getMessage());
            // Handle the array out of bounds exception
            System.err.println("Please check the array index.");
        } catch (ArithmeticException e) {
            System.err.println("Caught ArithmeticException: " + e.getMessage());
            // Handle the arithmetic exception (division by zero)
            System.err.println("Cannot divide by zero.");
        } catch (Exception e) {
            System.err.println("Caught a general Exception: " + e.getMessage());
            // Handle any other exception that might occur
            System.err.println("An unexpected error occurred.");
        } finally {
            System.out.println("Finally block executed.");
            // Code that always runs, regardless of exceptions
        }

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

Explanation:

  • The try block encloses the code that may throw exceptions.
  • Each catch block handles a specific type of exception. The catch block's parameter specifies the type of exception it can handle (e.g., ArrayIndexOutOfBoundsException, ArithmeticException).
  • If an exception occurs within the try block, the Java runtime searches for a catch block that matches the type of the exception.
  • If a matching catch block is found, the code within that block is executed.
  • The finally block (optional) contains code that will *always* be executed, regardless of whether an exception was thrown or caught. It's often used for cleanup tasks like closing resources.

Order of Catch Blocks

The order of catch blocks is crucial, especially when dealing with exception hierarchies. You should order your catch blocks from the most specific exception type to the most general exception type. If you put a more general exception type (like Exception) *before* a more specific type (like IOException), the more specific catch block will never be executed because the general catch block will catch all exceptions of that type and its subtypes.

For example, the following code is incorrect:

 try {
    // Code that might throw exceptions
} catch (Exception e) {
    System.err.println("Caught a general Exception.");
} catch (IOException e) {  // This will never be reached!
    System.err.println("Caught IOException.");
} 

The correct order is:

 try {
    // Code that might throw exceptions
} catch (IOException e) {
    System.err.println("Caught IOException.");
} catch (Exception e) {
    System.err.println("Caught a general Exception.");
} 

In the corrected example, if an IOException is thrown, the IOException catch block will handle it. If any other type of exception is thrown, the Exception catch block will handle it. If IOException inherits from `Exception`, catching `Exception` first renders the `IOException` catch block unreachable.