Bugs and errors in code are inevitable
, so it’s crucial not just to find them but also to handle them properly. If a program doesn’t know how to react to errors, it might just crash unexpectedly. Let’s break down the types of errors and how to manage them effectively.
Checked and Unchecked Exceptions
Errors in Java are divided into two main categories: unchecked exceptions and checked exceptions.
Unchecked Exceptions
Unchecked exceptions are errors that you don’t necessarily have to handle explicitly. If one of these occurs, the program crashes unless you catch and handle it.
Examples:
ArithmeticException
– division by zero.NullPointerException
– trying to access an object that isnull
.ArrayIndexOutOfBoundsException
– accessing an invalid index in an array.StringIndexOutOfBoundsException
– accessing an invalid index in a string.
These exceptions inherit from RuntimeException
, and the compiler doesn’t force you to handle them. However, ignoring them entirely can lead to program crashes, making debugging harder. It’s usually better to either adjust the logic to prevent such errors or handle them gracefully using try-catch
, so you can continue testing and improving your program.
Checked Exceptions
Checked exceptions, on the other hand, must be handled. If you don’t handle them, the code won’t compile. You need to either catch the exception using try-catch
or throw it further using throws
.
Examples:
IOException
– errors when working with files.SQLException
– database-related errors.FileNotFoundException
– trying to open a file that doesn’t exist.
These exceptions inherit from Exception
(but not RuntimeException
), which means you are required to handle them. Lesson 18: Exception vs. RuntimeException in Java: What’s the Deal?
Error Handling in Action
Handling errors properly ensures that your program doesn’t just crash but instead provides useful feedback and continues running where possible.
Example 1: Division by Zero (Unchecked Exception – Optional Handling)
If your program tries to divide by zero without handling it, it will crash. Here’s how to prevent that:
public class DivisionExample {
public static void main(String[] args) {
try {
int result = 10 / 0; // Error: division by zero
} catch (ArithmeticException e) {
System.out.println("Error: Cannot divide by zero.");
}
}
}
Code Breakdown:
- The division is inside a
try
block. - If an error occurs, the
catch
block catches theArithmeticException
. - Instead of crashing, the program prints a friendly message and continues running.
What Happens When You Run It?
- The program attempts to divide by zero inside
try
. - A
ArithmeticException
is triggered. - The
try
block stops executing, and control jumps tocatch
. - The program prints:
Error: Cannot divide by zero.
- The program continues running if there’s more code below.
What is ArithmeticException
?
- It’s part of the Java standard library (
java.lang
package). - It’s a subclass of
RuntimeException
, making it an unchecked exception. - Java does not force you to handle it.
What is e
in catch (ArithmeticException e)
?
- It’s a variable storing details about the error.
- When the exception occurs (
10 / 0
), it’s automatically passed toe
. - You can use
e.getMessage()
to get a description of the error.
Example:
catch (ArithmeticException e) {
System.out.println("Error: " + e.getMessage());
}
Output:
Error: / by zero
If you want a full error trace for debugging, use:
catch (ArithmeticException e) {
e.printStackTrace();
}
Example 2: Opening a File (Checked Exception – Must Be Handled)
If a file is missing, your program won’t even compile unless you handle the exception.
import java.io.*;
public class FileExample {
public static void main(String[] args) {
try {
BufferedReader reader = new BufferedReader(new FileReader("data.txt"));
System.out.println(reader.readLine());
reader.close();
} catch (FileNotFoundException e) {
System.out.println("Error: File not found.");
} catch (IOException e) {
System.out.println("Error reading the file.");
}
}
}
How It Works:
- The program tries to open
data.txt
. - If the file doesn’t exist,
FileNotFoundException
is caught. - If there’s an issue reading the file,
IOException
is caught. - The compiler requires handling these exceptions because they are checked exceptions.
Advanced Error Handling
In larger applications, handling errors properly is even more critical. Instead of spreading try-catch
blocks all over the code, it’s better to centralize error handling using custom exception classes.
Why Use Custom Exceptions?
- Makes error messages more meaningful.
- Centralizes error handling for better organization.
- Allows for better reusability and flexibility in error management.
Steps for Better Error Handling:
- Create a custom exception class – Give the error a meaningful name and message.
- Throw the exception where needed – When an error condition is detected, throw the exception instead of handling it immediately.
- Catch and handle it in a centralized place – Keep the handling logic in one place to maintain clean code.
Key Takeaways
- Unchecked exceptions (
RuntimeException
) don’t require handling but may cause crashes. - Checked exceptions (
Exception
, excludingRuntimeException
) must be handled, or the program won’t compile. - Simple error handling with
try-catch
helps programs recover gracefully. - Advanced error handling involves creating structured ways to manage errors for better scalability.
Proper error handling makes your code more reliable, predictable, and user-friendly, ensuring that your program doesn’t just crash whenever something unexpected happens.