Exception Handling
35 minException handling is crucial for building robust Java applications that gracefully handle errors and unexpected situations. Exceptions are events that disrupt normal program flow. Java's exception system provides structured error handling through try-catch blocks, exception types, and exception propagation. Understanding exception handling helps you write programs that fail gracefully and provide meaningful error feedback.
Java has two types of exceptions: checked exceptions (must be handled or declared) and unchecked exceptions (RuntimeException and its subclasses, don't need to be declared). Checked exceptions represent recoverable conditions that callers should handle. Unchecked exceptions represent programming errors (like NullPointerException) that usually indicate bugs. Understanding exception types helps you handle errors appropriately.
Try-catch blocks enable you to handle exceptions gracefully. The `try` block contains code that might throw exceptions. The `catch` block handles specific exception types. Multiple catch blocks can handle different exception types, with more specific exceptions caught first. The `finally` block always executes, useful for cleanup (closing files, releasing resources). Understanding try-catch-finally helps you handle errors and ensure cleanup.
Try-with-resources (Java 7+) automatically closes resources that implement `AutoCloseable`. This eliminates the need for explicit `finally` blocks for resource cleanup and prevents resource leaks. Resources declared in try-with-resources are automatically closed, even if exceptions occur. This is the preferred way to handle file I/O, database connections, and other resources. Understanding try-with-resources helps you write safer, cleaner code.
Exception propagation allows exceptions to bubble up the call stack until caught. Methods can declare exceptions they throw using `throws` in the method signature. Callers must either handle these exceptions or declare them in their own `throws` clause. This enables centralized error handling at appropriate levels. Understanding exception propagation helps you design error handling strategies.
Best practices include catching specific exceptions (not just `Exception`), using try-with-resources for resource management, providing meaningful error messages, logging exceptions for debugging, and handling exceptions at appropriate levels. Don't catch exceptions you can't handle meaningfully—let them propagate. Understanding exception handling enables you to build robust, fault-tolerant Java applications.
Key Concepts
- Exceptions disrupt normal program flow and must be handled.
- Try-catch blocks handle exceptions gracefully.
- Checked exceptions must be handled or declared with throws.
- Finally blocks always execute for cleanup.
- Try-with-resources automatically closes resources.
Learning Objectives
Master
- Using try-catch blocks for exception handling
- Understanding checked vs unchecked exceptions
- Working with try-with-resources for resource management
- Handling exceptions at appropriate levels
Develop
- Error handling and defensive programming thinking
- Understanding exception propagation and handling strategies
- Designing robust, fault-tolerant applications
Tips
- Use try-with-resources for file I/O and database connections.
- Catch specific exceptions, not just Exception.
- Provide meaningful error messages in catch blocks.
- Don't catch exceptions you can't handle—let them propagate.
Common Pitfalls
- Catching Exception too broadly, hiding real problems.
- Not using try-with-resources, causing resource leaks.
- Swallowing exceptions silently, making debugging impossible.
- Not handling checked exceptions, causing compilation errors.
Summary
- Exception handling enables graceful error management.
- Try-catch blocks handle exceptions; finally ensures cleanup.
- Try-with-resources automatically closes resources.
- Understanding exception handling enables robust applications.
- Proper exception handling improves application reliability.
Exercise
Write a program that demonstrates exception handling with different scenarios.
import java.util.Scanner;
public class ExceptionHandling {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
System.out.print("Enter a number: ");
String input = scanner.nextLine();
int number = Integer.parseInt(input);
int result = 100 / number;
System.out.println("Result: " + result);
} catch (NumberFormatException e) {
System.out.println("Error: Please enter a valid number");
} catch (ArithmeticException e) {
System.out.println("Error: Cannot divide by zero");
} catch (Exception e) {
System.out.println("Unexpected error: " + e.getMessage());
} finally {
System.out.println("This block always executes");
scanner.close();
}
}
}