Exceptions
### Exception in Java
An exception in Java is an event that disrupts the normal flow of the program's instructions during execution. It is an object which is thrown at runtime and represents an error or an unexpected event.
### Types of Exceptions
1. **Checked Exceptions:**
- **Description:** These are exceptions that are checked at compile-time. They are subclasses of `Exception` (excluding `RuntimeException`).
- **Examples:** `IOException`, `SQLException`, `FileNotFoundException`.
- **Handling:** Must be either caught using a `try-catch` block or declared to be thrown using the `throws` keyword in the method signature.
2. **Unchecked Exceptions:**
- **Description:** These are exceptions that are not checked at compile-time. They are subclasses of `RuntimeException`.
- **Examples:** `NullPointerException`, `ArrayIndexOutOfBoundsException`, `ArithmeticException`.
- **Handling:** Can be caught using a `try-catch` block, but it's not mandatory to declare them using the `throws` keyword.
3. **Error:**
- **Description:** These are not exceptions but problems that arise beyond the control of the user or the programmer. They are subclasses of `Error`.
- **Examples:** `OutOfMemoryError`, `StackOverflowError`.
- **Handling:** Typically not caught because they are usually irrecoverable.
### Handling Exceptions
1. **Try-Catch Block:**
- **Scenario:** Use this when you expect a specific block of code to potentially throw an exception.
- **Example:**
```java
try {
// Code that may throw an exception
int result = 10 / 0;
} catch (ArithmeticException e) {
// Handling exception
System.out.println("ArithmeticException caught: " + e.getMessage());
}
```
2. **Try-Catch-Finally Block:**
- **Scenario:** Use this when you need to ensure that some code is executed regardless of whether an exception is thrown or not.
- **Example:**
```java
try {
// Code that may throw an exception
int[] arr = new int[5];
arr[10] = 50;
} catch (ArrayIndexOutOfBoundsException e) {
// Handling exception
System.out.println("ArrayIndexOutOfBoundsException caught: " + e.getMessage());
} finally {
// Code to be executed regardless of an exception
System.out.println("Finally block executed.");
}
```
3. **Throwing Exceptions:**
- **Scenario:** Use this when you want to explicitly throw an exception.
- **Example:**
```java
public void validateAge(int age) {
if (age < 18) {
throw new IllegalArgumentException("Age must be at least 18.");
}
}
```
4. **Throws Keyword:**
- **Scenario:** Use this in a method signature to declare that the method might throw certain exceptions.
- **Example:**
```java
public void readFile(String filePath) throws IOException {
FileReader file = new FileReader(filePath);
BufferedReader fileInput = new BufferedReader(file);
// Read and process the file
}
```
### Step-by-Step Explanation for Visualizing and Remembering
1. **Identify the Code Block:** Determine which part of your code might throw an exception.
2. **Use Try-Catch for Specific Handling:**
- Wrap the code block in a `try` block.
- Use `catch` blocks to handle specific exceptions.
3. **Ensure Clean-Up with Finally:**
- Add a `finally` block if you have resources that need to be cleaned up or code that must run irrespective of an exception.
4. **Explicitly Throw Exceptions:**
- Use the `throw` keyword if you need to manually throw an exception based on certain conditions.
5. **Declare Exceptions with Throws:**
- Use the `throws` keyword in method signatures to indicate that the method may throw specific exceptions.
### Example Scenario
**Scenario: Reading a File**
1. **Code Block Identification:**
- Reading a file might throw `FileNotFoundException` or `IOException`.
2. **Try-Catch Block:**
```java
public void readFile(String filePath) {
try {
FileReader file = new FileReader(filePath);
BufferedReader fileInput = new BufferedReader(file);
String line;
while ((line = fileInput.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.out.println("I/O error occurred: " + e.getMessage());
}
}
```
3. **Using Finally:**
```java
public void readFile(String filePath) {
BufferedReader fileInput = null;
try {
FileReader file = new FileReader(filePath);
fileInput = new BufferedReader(file);
String line;
while ((line = fileInput.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.out.println("I/O error occurred: " + e.getMessage());
} finally {
try {
if (fileInput != null) {
fileInput.close();
}
} catch (IOException e) {
System.out.println("Error closing the file: " + e.getMessage());
}
}
}
```
By following this structured approach, you can effectively handle exceptions in Java and ensure your program behaves robustly in the face of unexpected events.