In Java, exceptions follow a hierarchical structure where all exceptions inherit from the Throwable
class. Understanding this hierarchy is crucial for proper exception handling.
Java Exception Hierarchy Tree
Throwable (Top-level class)
├── Error (Unchecked)
│ ├── VirtualMachineError
│ │ ├── OutOfMemoryError
│ │ └── StackOverflowError
│ └── AssertionError
│
└── Exception (Can be Checked or Unchecked)
├── RuntimeException (Unchecked)
│ ├── NullPointerException
│ ├── ArrayIndexOutOfBoundsException
│ ├── ArithmeticException
│ ├── IllegalArgumentException
│ └── NumberFormatException
│
├── IOException (Checked)
│ ├── FileNotFoundException
│ └── EOFException
│
├── SQLException (Checked)
└── InterruptedException (Checked)
Key Categories
1. Throwable
(Root Class)
- Superclass of all errors and exceptions.
- Contains methods like
getMessage()
,printStackTrace()
.
2. Error
(Unchecked)
-
Serious system-level issues (e.g.,
OutOfMemoryError
,StackOverflowError
). - Not meant to be caught (usually JVM-level problems).
3. Exception
(Can be Checked or Unchecked)
-
Checked Exceptions (Must be handled at compile time):
- E.g.,
IOException
,SQLException
.
- E.g.,
-
Unchecked Exceptions (
RuntimeException
and its subclasses):- E.g.,
NullPointerException
,ArithmeticException
.
- E.g.,
Order of Catching Exceptions
When handling multiple exceptions in catch
blocks:
- Child exceptions must come before parent exceptions (most specific → least specific).
- If a parent exception is caught first, child exceptions will never be reached (compiler error).
✅ Correct Order
try {
// Risky code
} catch (NullPointerException e) { // Child
System.out.println("NullPointerException occurred");
} catch (RuntimeException e) { // Parent
System.out.println("RuntimeException occurred");
} catch (Exception e) { // Grandparent
System.out.println("General Exception occurred");
}
❌ Wrong Order (Compilation Error)
try {
// Risky code
} catch (Exception e) { // Catches ALL exceptions first
System.out.println("General Exception occurred");
} catch (NullPointerException e) { // Unreachable (compiler error)
System.out.println("NullPointerException occurred");
}
Common Exceptions in Order of Specificity
Exception Type | Hierarchy Level | Checked/Unchecked |
---|---|---|
NullPointerException |
Child of RuntimeException
|
Unchecked |
ArrayIndexOutOfBoundsException |
Child of RuntimeException
|
Unchecked |
ArithmeticException |
Child of RuntimeException
|
Unchecked |
IOException |
Direct child of Exception
|
Checked |
FileNotFoundException |
Child of IOException
|
Checked |
Exception |
Parent of all exceptions | Checked (general) |
Throwable |
Root class | Rarely caught |
Best Practices
-
Catch specific exceptions first (e.g.,
FileNotFoundException
beforeIOException
). -
Avoid catching
Throwable
orException
unnecessarily (can hide bugs). -
Use
RuntimeException
for programming errors (e.g., invalid arguments). - Use checked exceptions for recoverable errors (e.g., file not found).
Example: Proper Exception Handling
import java.io.*;
public class ExceptionHierarchyDemo {
public static void main(String[] args) {
try {
BufferedReader br = new BufferedReader(new FileReader("test.txt"));
System.out.println(br.readLine());
} catch (FileNotFoundException e) { // More specific
System.out.println("File not found!");
} catch (IOException e) { // More general
System.out.println("IO Error!");
} catch (Exception e) { // Fallback
System.out.println("Unknown error!");
}
}
}
Output if file doesn't exist:
File not found!
Conclusion
-
Throwable
is the root of all exceptions. -
Error
is for JVM/system failures (usually not caught). -
Exception
has checked (must handle) and unchecked (RuntimeException
) types. - Catch specific exceptions before general ones to avoid unreachable code.
Understanding this hierarchy helps in writing robust error-handling code in Java. 🚀
Top comments (0)