Exception Handling Fundamentals
Java's exception handling mechanism provides robust error management through try-catch-finally constructs. The following examples demonstrate core concepts including exception propagation, nested handlers, and finally block execution semantics.
Basic Exception Management
The first example ilustrates fundamental expection catching with multiple handlers and guaranteed cleanup:
package com.exceptiontests;
public class BasicExceptionDemo {
public static void main(String[] args) {
int numerator = 10, denominator = 0, result;
try {
result = numerator / denominator; // Triggers arithmetic exception
} catch (ArithmeticException ae) {
System.err.println("Division error: " + ae.getMessage());
} catch (Exception generic) {
if (generic instanceof ArithmeticException) {
System.err.println("Arithmetic issue detected");
} else {
System.err.println("Unexpected error: " + generic.getMessage());
}
} finally {
System.out.println("Cleanup section executed");
}
}
}
Execution output:
Division error: / by zero
Cleanup section executed
Nested Exception Handlers
This pattern shows how inner catch blocks can intercept exceptions before they reach outer handlers:
package com.exceptiontests;
public class NestedCatchExample {
public static void main(String[] args) {
try {
try {
String text = "sample";
char invalidChar = text.charAt(50); // Throws StringIndexOutOfBoundsException
} catch (StringIndexOutOfBoundsException siobe) {
System.out.println("String index error - Inner handler");
}
// This line executes because the inner exception was handled
int[] numbers = new int[5];
int value = numbers[10]; // Would throw exception if reached
} catch (ArrayIndexOutOfBoundsException aioobe) {
System.out.println("Array index error - Outer handler");
} catch (Exception e) {
System.out.println("Generic outer catch");
}
}
}
Program output:
String index error - Inner handler
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 5
Note: The outer catch doesn't execute for the inner exception
Mismatched Exception Types in Nested Blocks
When inner catch blocks don't match the thrown exception type, propagation continues to outer handlers:
package com.exceptiontests;
public class MismatchedCatchDemo {
public static void main(String[] args) {
try {
try {
throw new NullPointerException("Resource is null");
} catch (IllegalArgumentException iae) {
System.out.println("Illegal argument - Inner");
}
System.out.println("This won't execute");
} catch (NullPointerException npe) {
System.out.println("Null pointer caught - Outer");
} catch (RuntimeException re) {
System.out.println("Runtime exception - Outer fallback");
}
}
}
Output demonstrates outer handler activation:
Null pointer caught - Outer
Hierarchical Finally Block Execution
Multiple nested try-catch-finally structures create a cascading execution pattern:
package com.exceptiontests;
public class HierarchicalFinallyBlocks {
public static void main(String[] args) {
try {
System.out.println("Layer 1 - Entry");
try {
System.out.println("Layer 2 - Entry");
try {
System.out.println("Layer 3 - Entry");
int computation = 100 / 0; // Exception origin
System.out.println("Layer 3 - Exit"); // Unreachable
} catch (RuntimeException re) {
System.out.println("Layer 3 Exception: " + re.getClass().getSimpleName());
} finally {
System.out.println("Layer 3 Finally");
}
System.out.println("Layer 2 - Middle");
} catch (Exception ex) {
System.out.println("Layer 2 Exception: " + ex.getClass().getSimpleName());
} finally {
System.out.println("Layer 2 Finally");
}
System.out.println("Layer 1 - Middle");
} catch (Throwable t) {
System.out.println("Layer 1 Exception: " + t.getClass().getSimpleName());
} finally {
System.out.println("Layer 1 Finally");
}
}
}
Execution trace:
Layer 1 - Entry
Layer 2 - Entry
Layer 3 - Entry
Layer 3 Exception: ArithmeticException
Layer 3 Finally
Layer 2 - Middle
Layer 2 Finally
Layer 1 - Middle
Layer 1 Finally
JVM Termination and Final Block Bypass
Calling System.exit() abruptly terminates the JVM, preventing finally block execution:
package com.exceptiontests;
public class JVMExitVsFinally {
public static void main(String[] args) {
try {
System.out.println("Application starting");
throw new RuntimeException("Critical initialization failure");
} catch (RuntimeException rte) {
System.err.println("Fatal error: " + rte.getMessage());
System.exit(1); // JVM terminates here
} finally {
// This block never executes due to System.exit()
System.out.println("Cleanup operations skipped");
}
}
}
Program output:
Application starting
Fatal error: Critical initialization failure
Key Observation: The finally block's code is bypassed when System.exit() is invoked, as the JVM halts immediately.