7.2 Exception Handling
Handling Exceptions
Exception handling is a critical aspect of programming that allows developers to manage errors and unexpected events gracefully. In this module, you will learn about the different types of exceptions, how to handle them effectively, and the importance of throwing exceptions in your code. By mastering exception handling, you can enhance the reliability and robustness of your Java applications.
Exception Handling in Java
1. Try/Catch Syntax
Exception handling in Java is done using the try/catch block. The code that might throw an exception is placed inside the try block, and the exception is handled in the catch block.
Example:
try {
int result = 10 / 0; // Will throw ArithmeticException
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero");
}
2. Chaining Catch Blocks
Multiple catch blocks can be chained to handle different types of exceptions. The most specific exception should be caught first, followed by more general ones.
Example:
try {
int[] arr = new int[5];
arr[10] = 50; // Will throw ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Index out of bounds");
} catch (Exception e) {
System.out.println("General exception");
}
3. Finally Syntax
The finally block is used to execute code regardless of whether an exception is thrown or not. It is typically used to release resources like closing files or database connections.
Example:
try {
int num = Integer.parseInt("abc"); // Will throw NumberFormatException
} catch (NumberFormatException e) {
System.out.println("Invalid number format");
} finally {
System.out.println("This will always execute");
}
4. Understanding Exception Types
Introduction
Exceptions in Java are classified into different types based on the hierarchy and nature of the exception. Java provides a robust exception hierarchy, and exceptions are categorized into two main types: checked and runtime (unchecked) exceptions.
Reviewing the Exception Hierarchy
At the top of the exception hierarchy is the Throwable class, which has two subclasses: Error and Exception.
- Error: Represents serious problems that a program should not try to handle (e.g.,
OutOfMemoryError). - Exception: Represents exceptions that a program can handle.
Runtime vs. Checked Exceptions
- Checked Exceptions: These exceptions must be either caught or declared in the method signature. They are checked at compile-time (e.g.,
IOException,SQLException). - Runtime (Unchecked) Exceptions: These exceptions do not need to be explicitly handled and are checked at runtime (e.g.,
NullPointerException,ArrayIndexOutOfBoundsException).
Important Runtime Exceptions
Some common runtime exceptions include:
NullPointerExceptionArrayIndexOutOfBoundsExceptionArithmeticExceptionIllegalArgumentException
Important Checked Exceptions
Common checked exceptions include:
IOExceptionSQLExceptionClassNotFoundException
Revisiting Chained Catch Blocks
Multiple exceptions can be handled using chained catch blocks, which allow for specific exception handling. It is important to remember that more specific exceptions should be caught first.
5. Throwing Exceptions
Introduction
In addition to handling exceptions, you can also throw exceptions explicitly using the throw keyword. This is typically done when you want to signal that an error has occurred during the execution of a method.
How to Throw
To throw an exception, use the throw keyword followed by an instance of an exception.
Example:
public void divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("Cannot divide by zero");
}
System.out.println(a / b);
}
Rethrowing Exceptions
Sometimes, you may want to catch an exception and then throw it again to be handled by a higher-level method. This is known as rethrowing an exception.
Example:
try {
throw new IOException("IO error");
} catch (IOException e) {
System.out.println("Caught IOException, rethrowing");
throw e;
}
Demo: Rethrowing
In this demo, we’ll see how to catch an exception, handle it partially, and then rethrow it for further handling at a higher level.
6. Overriding and Overloading Methods with Exceptions
When overriding a method, the overriding method cannot throw more checked exceptions than the method it overrides. However, it can throw fewer exceptions or runtime exceptions.
Example:
class Parent {
public void readFile() throws IOException {
// Reading file logic
}
}
class Child extends Parent {
@Override
public void readFile() {
// No need to declare IOException
}
}
In the case of method overloading, each overloaded method can throw different exceptions as per its signature.
7. Printing Exceptions
The printStackTrace() method prints the details of an exception, including the method call stack. This helps in debugging by showing where the exception occurred.
Example:
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
e.printStackTrace(); // Prints stack trace of the exception
}
8. Conclusion
In this tutorial, we’ve covered exception handling in Java, including the try/catch syntax, checked vs. unchecked exceptions, and throwing and rethrowing exceptions. Exception handling is an essential part of writing robust Java applications, and mastering these concepts will help you handle errors gracefully and maintain clean, readable code.