Catching and Handling Exceptions

1. Exception Handling Constructs

Java provides three main constructs:

try {
    // risky code
} catch (Exception e) {
    // handle exception
} finally {
    // cleanup
}

2. The try Block

try {
    int result = 10 / 0;
}

By itself, this is invalid because there is no catch or finally.


3. The catch Block

try {
    // risky code
} catch (IOException e) {
    // handle IOException
} catch (SQLException e) {
    // handle SQLException
}

Catch Order

Put more specific exceptions before their parent exception.

catch (FileNotFoundException e) { }
catch (IOException e) { }

This is correct because FileNotFoundException is a subclass of IOException.

The reverse order is invalid:

catch (IOException e) { }
catch (FileNotFoundException e) { } // Error

The second catch can never be reached.


4. Multi-Catch

Since Java 7, multiple unrelated exception types can be handled by one catch block.

try {
    // risky code
} catch (IOException | SQLException e) {
    // handle both
}
catch (IOException | FileNotFoundException e) // Error

because FileNotFoundException is already an IOException.


5. The finally Block

try {
    // use resource
} catch (Exception e) {
    // handle error
} finally {
    // cleanup
}

For example:

finally {
    connection.close();
}

Note: finally may not execute if the JVM terminates abruptly.


6. Try-With-Resources

Since Java 7, try-with-resources automatically closes resources that implement AutoCloseable.

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    System.out.println(br.readLine());
}

After the try block finishes, br is automatically closed.

This is generally preferred over manually closing resources in finally.

Multiple Resources

try (
    FileReader reader = new FileReader("data.txt");
    BufferedReader br = new BufferedReader(reader)
) {
    System.out.println(br.readLine());
}
br closes first
↓
reader closes second

7. Catch/Finally with Try-With-Resources

You can still use catch and finally:

try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
    System.out.println(br.readLine());
} catch (IOException e) {
    e.printStackTrace();
} finally {
    System.out.println("Finished");
}

The resources are closed before the catch or finally block executes.


8. Suppressed Exceptions

Sometimes two exceptions occur:

  1. The try block throws an exception.

  2. Closing the resource also throws an exception.

With try-with-resources:

try exception
      ↓
becomes the main exception

close exception
      ↓
becomes a suppressed exception

You can access suppressed exceptions using:

e.getSuppressed();

Example:

catch (Exception e) {
    for (Throwable suppressed : e.getSuppressed()) {
        System.out.println(suppressed);
    }
}

This prevents the original exception from being lost.


9. Best Practices


Summary

Construct Purpose
try Contains potentially risky code
catch Handles an exception
finally Performs cleanup after try/catch
Multi-catch Handles multiple exception types together
Try-with-resources Automatically closes resources
getSuppressed() Gets exceptions thrown during resource closing