Skip to content
Dev Dump

🎯 Java Exception Handling: Complete Guide

Exception handling is fundamental to building reliable, robust applications. It enables graceful error recovery, prevents application crashes, and provides meaningful error information.

  • An exception is an event that disrupts the normal flow of the program
  • It is an object that describes an error condition
  • Exception handling allows programs to recover gracefully from errors

CategoryDescriptionExamples
CheckedChecked at compile timeIOException, SQLException
UncheckedChecked at runtimeNullPointerException, ArrayIndexOutOfBoundsException
ErrorsSerious issues, not recoverableOutOfMemoryError, StackOverflowError
FeatureCheckedUnchecked
Compile-time check✅ Yes❌ No
Must handleYes (try-catch or throws)Optional
Typical useFile I/O, DB access, NetworkLogic bugs, NullPointer
SuperclassExceptionRuntimeException
Recovery possibleOften yesUsually no

java.lang.Throwable
├── Error (Unchecked, JVM-level)
│ ├── OutOfMemoryError
│ ├── StackOverflowError
│ ├── VirtualMachineError
│ └── LinkageError
└── Exception
├── Checked Exception (must handle)
│ ├── IOException
│ ├── SQLException
│ ├── ClassNotFoundException
└── Unchecked Exception (RuntimeException & subclasses)
├── NullPointerException
├── IllegalArgumentException
├── ArrayIndexOutOfBoundsException
├── ClassCastException
├── NumberFormatException
└── ConcurrentModificationException
TypeWhen ThrownMust HandleExample
ErrorJVM/system level❌ NoOutOfMemoryError
Checked ExceptionApplication logic✅ YesIOException
Unchecked ExceptionRuntime logic errors❌ NoNullPointerException

Use try to wrap code that might throw exceptions.

try {
int a = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero!");
} finally {
System.out.println("Always executes");
}
  • try: Monitors the block for exceptions
  • catch: Handles specific exception types
  • finally: Always executes, used for cleanup (like closing files)

try {
int[] arr = new int[5];
System.out.println(arr[10]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Index out of range!");
} catch (Exception e) {
System.out.println("Some error occurred");
}
public class MultipleCatchExample {
public static void process(String input) {
try {
int number = Integer.parseInt(input);
int result = 100 / number;
System.out.println("Result: " + result);
} catch (NumberFormatException e) {
System.err.println("Invalid number format: " + input);
} catch (ArithmeticException e) {
System.err.println("Division by zero");
} catch (Exception e) {
System.err.println("Unexpected error: " + e.getMessage());
}
}
// Java 7+ multi-catch
public static void multiCatch(String input) {
try {
int number = Integer.parseInt(input);
int result = 100 / number;
System.out.println("Result: " + result);
} catch (NumberFormatException | ArithmeticException e) {
System.err.println("Input error: " + e.getMessage());
}
}
}

  • Used when a method declares it might throw an exception
  • Moves responsibility to the caller
  • Caller must handle the exception or declare it further
public class ThrowsExample {
public void readFile() throws IOException {
FileReader fr = new FileReader("file.txt");
// File operations
}
public void processFile() throws IOException, SQLException {
readFile(); // This method throws IOException
// Database operations that might throw SQLException
}
// Caller must handle exceptions
public static void main(String[] args) {
ThrowsExample example = new ThrowsExample();
try {
example.processFile();
} catch (IOException | SQLException e) {
System.err.println("Error: " + e.getMessage());
}
}
}

public class ThrowExample {
public static void validateAge(int age) {
if (age < 18) {
throw new ArithmeticException("Not eligible to vote");
}
if (age < 0) {
throw new IllegalArgumentException("Age cannot be negative");
}
System.out.println("Valid age: " + age);
}
public static void main(String[] args) {
try {
validateAge(15); // Will throw exception
} catch (ArithmeticException e) {
System.err.println("Validation failed: " + e.getMessage());
}
}
}
public class CustomValidation {
public static void validateEmail(String email) {
if (email == null || !email.contains("@")) {
throw new IllegalArgumentException("Invalid email format: " + email);
}
System.out.println("Valid email: " + email);
}
}

class AgeException extends Exception {
AgeException(String msg) {
super(msg);
}
}
// Usage
public class CustomExceptionExample {
public static void validateAge(int age) throws AgeException {
if (age < 0) {
throw new AgeException("Invalid Age: " + age);
}
if (age > 150) {
throw new AgeException("Age seems unrealistic: " + age);
}
System.out.println("Valid age: " + age);
}
public static void main(String[] args) {
try {
validateAge(-5); // Will throw AgeException
} catch (AgeException e) {
System.err.println("Age validation failed: " + e.getMessage());
}
}
}

ExceptionDescriptionExample
NullPointerExceptionAccessing a null object referenceString str = null; str.length();
ArrayIndexOutOfBoundsExceptionInvalid array indexint[] arr = new int[5]; arr[10];
ClassNotFoundExceptionClass not found at runtimeClass.forName("NonExistentClass");
IllegalArgumentExceptionInvalid method argumentInteger.parseInt("abc");
NumberFormatExceptionInvalid conversionInteger.parseInt("abc");
ArithmeticExceptionMathematical errorint result = 10 / 0;
ClassCastExceptionInvalid type castingObject obj = "String"; Integer num = (Integer) obj;
  • Catch only specific exceptions - avoid catching generic Exception
  • Always clean up with finally or try-with-resources
  • Avoid empty catch blocks - always handle or log exceptions
  • Don’t use exceptions for flow control - they’re expensive
  • Log exceptions properly with context information
  • Rethrow exceptions when appropriate to maintain the call stack