Catching and Handling Exceptions
1. Exception Handling Constructs
Java provides three main constructs:
-
try— contains code that may throw an exception. -
catch— handles a specific exception. -
finally— runs aftertry/catch, usually for cleanup.
try {
// risky code
} catch (Exception e) {
// handle exception
} finally {
// cleanup
}
2. The try Block
-
Put code that might throw an exception inside
try. -
A
tryblock must be followed by at least onecatchorfinally.
try {
int result = 10 / 0;
}
By itself, this is invalid because there is no catch or finally.
3. The catch Block
-
Handles exceptions thrown by the
tryblock. -
You can have multiple
catchblocks. -
Java executes the first matching
catchblock.
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
}
-
The exception types must be unrelated.
-
You cannot use parent and child types together.
catch (IOException | FileNotFoundException e) // Error
because FileNotFoundException is already an IOException.
5. The finally Block
-
finallyexecutes after thetry/catch. -
It normally executes whether an exception occurs or not.
-
Mainly used for cleanup.
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());
}
-
Resources are closed automatically.
-
They are closed in reverse order of their declaration.
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:
-
The
tryblock throws an exception. -
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
-
Use
try-catchwhen you need to handle an exception. -
Use
finallyfor cleanup when try-with-resources isn't suitable. -
Prefer try-with-resources for files, streams, sockets, database resources, etc.
-
Use multi-catch when different exceptions require the same handling.
-
Put specific
catchblocks before general ones.
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 |