Java Notes
Complete guide to Java
The Complete Hierarchy Tree
All exceptions and errors in Java form a class hierarchy rooted at Throwable:
Understanding Each Level
Level 1: java.lang.Object
Every class in Java extends Object. Throwable is no exception.
Level 2: java.lang.Throwable
The root of all errors and exceptions. Only objects of type Throwable (or its subclasses) can be thrown with the throw keyword and caught with catch.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Output:
Level 3a: java.lang.Error (DO NOT CATCH)
Errors represent serious problems that an application should NOT attempt to handle. They're typically caused by the JVM environment.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Output:
Common Errors:
| Error | Cause |
|---|---|
StackOverflowError | Infinite recursion or very deep call stack |
OutOfMemoryError | JVM cannot allocate more heap memory |
VirtualMachineError | JVM is broken or out of resources |
NoClassDefFoundError | Class was available at compile-time but not at runtime |
ExceptionInInitializerError | Static initializer threw an exception |
LinkageError | Class dependency issues |
Level 3b: java.lang.Exception (HANDLE THESE)
Exceptions represent conditions that a program should handle. They branch into two categories:
Checked vs Unchecked Exceptions
Checked Exceptions (Compile-Time)
The compiler forces you to handle these. If you don't use try-catch or declare throws, the code won't compile.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Output:
Unchecked Exceptions (Runtime Exceptions)
These extend RuntimeException. The compiler does NOT force you to handle them. They usually indicate programming bugs.
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Output:
| 1. NullPointerException | Cannot invoke "String.length()" because "str" is null |
| 2. ArrayIndexOutOfBoundsException | Index 5 out of bounds for length 3 |
| 3. ArithmeticException | / by zero |
| 4. ClassCastException | class java.lang.String cannot be cast to class java.lang.Integer |
| 5. NumberFormatException | For input string: "abc" |
| 6. IllegalArgumentException | timeout value is negative |
| 7. IllegalStateException | null |
| 8. StringIndexOutOfBoundsException | String index out of range: 10 |
Why Two Categories?
| Aspect | Checked | Unchecked |
|---|---|---|
| Extends | Exception (not RuntimeException) | RuntimeException |
| Compiler check | YES — must handle or declare | NO — optional handling |
| Typical cause | External factors (files, network, DB) | Programming bugs |
| When to use | Things beyond your control | Preventable logical errors |
| Examples | IOException, SQLException | NullPointerException, ClassCastException |
| Fix approach | Handle gracefully | Fix the code logic |
Exploring the Hierarchy Programmatically
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Output:
| IOException | Checked | YES | Parent: Exception |
| RuntimeException | Checked | NO | Parent: Exception |
| NullPointerException | Checked | NO | Parent: RuntimeException |
| FileNotFoundException | Checked | YES | Parent: IOException |
| IllegalArgumentException | Checked | NO | Parent: RuntimeException |
| NumberFormatException | Checked | NO | Parent: IllegalArgumentException |
| ArrayIndexOutOfBoundsException | Checked | NO | Parent: IndexOutOfBoundsException |
Throwable Class Methods
All exceptions inherit these methods from Throwable:
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Output:
| getMessage() | Calculation failed |
| toString() | java.lang.RuntimeException: Calculation failed |
| getCause() | java.lang.ArithmeticException: / by zero |
| java.lang.RuntimeException | Calculation failed |
| at ThrowableMethods.methodB(ThrowableMethods.java | 34) |
| at ThrowableMethods.methodA(ThrowableMethods.java | 28) |
| at ThrowableMethods.main(ThrowableMethods.java | 5) |
| Caused by | java.lang.ArithmeticException: / by zero |
| at ThrowableMethods.methodB(ThrowableMethods.java | 32) |
Catching at Different Hierarchy Levels
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Output:
| Caught as IOException | FileNotFoundException |
| Message | test.txt not found |
| Caught as Exception | NumberFormatException |
Practical Application: Exception Hierarchy in Method Design
Try it in WoHoCode
Edit the program, then run it here.
Run this example to see its output.
Output:
| null array | NULL ERROR: Array cannot be null |
| empty array | ARGUMENT ERROR: Array cannot be empty |
| valid array | Average: 20.00 |
Common Mistakes
1. Catching Throwable or Error
// ❌ BAD: Don't catch Throwable
try {
// code
} catch (Throwable t) {
// Catches Errors too! You can't recover from OutOfMemoryError
}
// ❌ BAD: Don't catch Error
try {
// code
} catch (Error e) {
// Usually pointless - JVM state is compromised
}
// ✅ GOOD: Catch Exception at most
try {
// code
} catch (Exception e) {
// Catches all recoverable exceptions
}2. Not Understanding Inheritance in Catches
// ❌ COMPILE ERROR: IOException is parent of FileNotFoundException
try {
// code
} catch (IOException e) {
// Catches FileNotFoundException too!
} catch (FileNotFoundException e) {
// UNREACHABLE! Compile error
}
// ✅ CORRECT: Most specific first
try {
// code
} catch (FileNotFoundException e) {
// Specific handling for file not found
} catch (IOException e) {
// General IO handling for other IO problems
}Interview Questions
Q1: Draw the Java Exception hierarchy.
Answer: Object → Throwable → branches into Error (unrecoverable: StackOverflowError, OutOfMemoryError) and Exception (recoverable). Exception branches into checked exceptions (IOException, SQLException) and RuntimeException (unchecked: NullPointerException, ArithmeticException).
Q2: What is the difference between checked and unchecked exceptions?
Answer: Checked exceptions (extend Exception but not RuntimeException) are verified at compile-time — you must handle or declare them. Unchecked exceptions (extend RuntimeException) are not checked by the compiler — they indicate bugs that should be fixed in code. External issues → checked; code bugs → unchecked.
Q3: Is NumberFormatException checked or unchecked? What's its hierarchy?
Answer: Unchecked. Hierarchy: NumberFormatException → IllegalArgumentException → RuntimeException → Exception → Throwable → Object.
Q4: Can we catch Error in Java? Should we?
Answer: Technically yes (Error extends Throwable). But you should NOT because: (1) Errors indicate the JVM/system is in an unrecoverable state, (2) catching OutOfMemoryError doesn't guarantee you have memory to handle it, (3) program behavior after catching an Error is unpredictable.
Q5: Why does Java have checked exceptions? Are they controversial?
Answer: Checked exceptions force developers to consider failure scenarios at compile time, making code more robust. However, they're controversial because they can clutter code, force boilerplate handlers, and violate encapsulation (implementation details leak through method signatures). Many modern languages (Kotlin, Scala) don't have checked exceptions.
Q6: What class should you extend to create a custom checked exception vs unchecked?
Answer: Extend Exception for a custom checked exception. Extend RuntimeException for a custom unchecked exception. Choose checked when callers can meaningfully recover; choose unchecked for programming errors.
Q8: What is the difference between ClassNotFoundException and NoClassDefFoundError?
A: ClassNotFoundException (checked) occurs when Class.forName() or ClassLoader can't find the class at runtime. NoClassDefFoundError (Error) occurs when the class was available at compile time but missing at runtime (e.g., deleted JAR). The former is recoverable; the latter usually isn't.
Q9: Can you catch Error in Java?
A: Technically yes — catch(Error e) or catch(Throwable t) compiles and runs. However, you generally SHOULD NOT because Errors represent unrecoverable conditions (OutOfMemoryError, StackOverflowError). Catching them may leave the JVM in an inconsistent state. Exception: sometimes catching OutOfMemoryError to log before shutdown.
Q10: Why is RuntimeException unchecked while IOException is checked?
A: RuntimeExceptions indicate programming bugs (null pointer, bad index) that could be prevented with proper code — forcing try-catch would clutter code without benefit. Checked exceptions (IOException, SQLException) represent external failures that even correct code can't prevent — the compiler ensures you handle or propagate them.
Q11: What are the most common RuntimeExceptions in Java?
A: NullPointerException (accessing null reference), ArrayIndexOutOfBoundsException (invalid array index), ClassCastException (invalid cast), IllegalArgumentException (bad method argument), IllegalStateException (method called at wrong time), NumberFormatException (invalid string-to-number), ConcurrentModificationException (collection modified during iteration).
Q12: How do you decide whether to make a custom exception checked or unchecked?
A: Make it checked (extend Exception) when the caller can reasonably recover and SHOULD be forced to handle it (e.g., InsufficientBalanceException). Make it unchecked (extend RuntimeException) when it indicates a programming error or when forcing callers to handle it provides no benefit (e.g., InvalidConfigurationException).
Continue the lesson path