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.
public class ThrowableDemo {
public static void main(String[] args) {
try {
// You can catch Throwable (but usually shouldn't)
throw new Throwable("I am a Throwable");
} catch (Throwable t) {
System.out.println("Class: " + t.getClass().getName());
System.out.println("Message: " + t.getMessage());
System.out.println("Is Exception? " + (t instanceof Exception));
System.out.println("Is Error? " + (t instanceof Error));
}
}
}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.
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.
import java.io.*;
import java.sql.*;
public class CheckedExceptions {
// ❌ WON'T COMPILE without throws or try-catch
// static void readFile() {
// FileReader reader = new FileReader("test.txt"); // IOException
// }
// ✅ Option 1: Declare with throws
static void readFile1() throws IOException {
FileReader reader = new FileReader("test.txt");
reader.close();
}
// ✅ Option 2: Handle with try-catch
static void readFile2() {
try {
FileReader reader = new FileReader("test.txt");
reader.close();
} catch (IOException e) {
System.out.println("Cannot read file: " + e.getMessage());
}
}
public static void main(String[] args) {
readFile2();
// Common checked exceptions:
System.out.println("Common Checked Exceptions:");
System.out.println(" - IOException (file/network I/O problems)");
System.out.println(" - SQLException (database problems)");
System.out.println(" - ClassNotFoundException (reflection)");
System.out.println(" - InterruptedException (thread interruption)");
System.out.println(" - FileNotFoundException (specific file missing)");
System.out.println(" - ParseException (date/number parsing)");
}
}Output:
Unchecked Exceptions (Runtime Exceptions)
These extend RuntimeException. The compiler does NOT force you to handle them. They usually indicate programming bugs.
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
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:
public class ThrowableMethods {
public static void main(String[] args) {
try {
methodA();
} catch (Exception e) {
// 1. getMessage() - returns the detail message
System.out.println("getMessage(): " + e.getMessage());
// 2. toString() - class name + message
System.out.println("toString(): " + e.toString());
// 3. getCause() - returns the cause (chained exception)
System.out.println("getCause(): " + e.getCause());
// 4. getStackTrace() - array of stack trace elements
System.out.println("\nStack Trace Elements:");
for (StackTraceElement elem : e.getStackTrace()) {
System.out.printf(" %s.%s() at line %d%n",
elem.getClassName(), elem.getMethodName(),
elem.getLineNumber());
}
// 5. printStackTrace() - prints to System.err
System.out.println("\nprintStackTrace():");
e.printStackTrace(System.out); // Redirect to stdout for demo
}
}
static void methodA() {
methodB();
}
static void methodB() {
// Exception chaining
try {
int result = 10 / 0;
} catch (ArithmeticException cause) {
throw new RuntimeException("Calculation failed", cause);
}
}
}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
import java.io.*;
public class CatchHierarchy {
public static void main(String[] args) {
// A catch block catches the specified type AND all its subclasses
// catch(Exception e) catches ALL exceptions
// catch(RuntimeException e) catches all unchecked exceptions
// catch(IOException e) catches IOException and FileNotFoundException
System.out.println("=== Polymorphic Exception Catching ===\n");
// Test 1: Catching with parent type
try {
throw new FileNotFoundException("test.txt not found");
} catch (IOException e) { // Catches FileNotFoundException too!
System.out.println("Caught as IOException: " + e.getClass().getSimpleName());
System.out.println(" Message: " + e.getMessage());
System.out.println(" Is FileNotFoundException? " + (e instanceof FileNotFoundException));
}
System.out.println();
// Test 2: Catching with grandparent type
try {
throw new NumberFormatException("bad number");
} catch (Exception e) { // Catches everything!
System.out.println("Caught as Exception: " + e.getClass().getSimpleName());
System.out.println(" Is RuntimeException? " + (e instanceof RuntimeException));
System.out.println(" Is IllegalArgumentException? " + (e instanceof IllegalArgumentException));
System.out.println(" Is NumberFormatException? " + (e instanceof NumberFormatException));
}
}
}Output:
| Caught as IOException | FileNotFoundException |
| Message | test.txt not found |
| Caught as Exception | NumberFormatException |
Practical Application: Exception Hierarchy in Method Design
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).
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Exception Hierarchy in Java.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, exception, handling, hierarchy
Related Java Master Course Topics