Java Exceptions Cheat Sheet

Exceptions are Java’s way of handling errors and unexpected conditions. This cheat sheet covers the exception hierarchy, common exceptions you’ll encounter, and patterns for handling them effectively.

Exception Hierarchy

Throwable
    |
    +-- Error (don't catch these)
    |       +-- OutOfMemoryError
    |       +-- StackOverflowError
    |       +-- VirtualMachineError
    |
    +-- Exception
            |
            +-- RuntimeException (unchecked)
            |       +-- NullPointerException
            |       +-- ArrayIndexOutOfBoundsException
            |       +-- IllegalArgumentException
            |       +-- IllegalStateException
            |       +-- ClassCastException
            |       +-- ArithmeticException
            |       +-- NumberFormatException
            |
            +-- IOException (checked)
            +-- SQLException (checked)
            +-- ClassNotFoundException (checked)

Checked vs Unchecked

Type Must Handle? Examples When to Use
Checked Yes (catch or declare) IOException, SQLException Recoverable conditions
Unchecked (Runtime) No NullPointerException, IllegalArgumentException Programming errors
Error No (don’t catch) OutOfMemoryError, StackOverflowError JVM problems

Basic Exception Handling

Try-Catch

try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("Cannot divide by zero: " + e.getMessage());
}

Try-Catch-Finally

FileReader reader = null;
try {
    reader = new FileReader("file.txt");
    // read file
} catch (FileNotFoundException e) {
    System.out.println("File not found: " + e.getMessage());
} finally {
    // Always executes, even if exception thrown
    if (reader != null) {
        try {
            reader.close();
        } catch (IOException e) {
            // Handle close error
        }
    }
}

Try-With-Resources (Java 7+)

// Resources auto-closed when block exits
try (FileReader reader = new FileReader("file.txt");
     BufferedReader br = new BufferedReader(reader)) {
    String line = br.readLine();
    System.out.println(line);
} catch (IOException e) {
    System.out.println("Error reading file: " + e.getMessage());
}
// No finally needed - resources closed automatically

Multiple Catch Blocks

try {
    // risky code
} catch (FileNotFoundException e) {
    // Handle file not found specifically
} catch (IOException e) {
    // Handle other IO errors
} catch (Exception e) {
    // Catch-all for anything else
}
// Order matters: specific exceptions first, general last

Multi-Catch (Java 7+)

try {
    // risky code
} catch (IOException | SQLException e) {
    // Handle either exception the same way
    System.out.println("Error: " + e.getMessage());
}

Throwing Exceptions

Throw Statement

public void setAge(int age) {
    if (age < 0) {
        throw new IllegalArgumentException("Age cannot be negative: " + age);
    }
    this.age = age;
}

public void withdraw(double amount) {
    if (amount > balance) {
        throw new IllegalStateException("Insufficient funds");
    }
    balance -= amount;
}

Throws Declaration

// Declare checked exceptions in method signature
public String readFile(String path) throws IOException {
    return Files.readString(Path.of(path));
}

// Multiple exceptions
public void processData(String path) throws IOException, SQLException {
    // code that might throw either
}

// Callers must handle or propagate
public void caller() {
    try {
        String content = readFile("data.txt");
    } catch (IOException e) {
        // handle it
    }
}

// Or propagate further
public void caller() throws IOException {
    String content = readFile("data.txt");
}

Common Exceptions Reference

NullPointerException

// Cause: calling method on null reference
String s = null;
s.length();  // NullPointerException

// Prevention
if (s != null) {
    s.length();
}

// Or use Optional
Optional.ofNullable(s).map(String::length).orElse(0);

// Java 14+ helpful messages show which variable was null
// "Cannot invoke String.length() because s is null"

ArrayIndexOutOfBoundsException

// Cause: accessing invalid array index
int[] arr = {1, 2, 3};
arr[5];  // ArrayIndexOutOfBoundsException

// Prevention
if (index >= 0 && index < arr.length) {
    arr[index];
}

IndexOutOfBoundsException

// Cause: invalid index in List or String
List<String> list = List.of("a", "b");
list.get(10);  // IndexOutOfBoundsException

String s = "hello";
s.charAt(10);  // StringIndexOutOfBoundsException

// Prevention
if (index >= 0 && index < list.size()) {
    list.get(index);
}

ClassCastException

// Cause: invalid type cast
Object obj = "hello";
Integer num = (Integer) obj;  // ClassCastException

// Prevention: check type first
if (obj instanceof Integer) {
    Integer num = (Integer) obj;
}

// Java 16+ pattern matching
if (obj instanceof Integer num) {
    // num is already cast
}

NumberFormatException

// Cause: parsing invalid number string
Integer.parseInt("abc");  // NumberFormatException
Double.parseDouble("12.34.56");  // NumberFormatException

// Prevention
public static Integer parseIntSafe(String s) {
    try {
        return Integer.parseInt(s);
    } catch (NumberFormatException e) {
        return null;  // or default value
    }
}

IllegalArgumentException

// Cause: invalid method argument
// Throw this in your own code for validation

public void setPercentage(int percent) {
    if (percent < 0 || percent > 100) {
        throw new IllegalArgumentException(
            "Percentage must be 0-100, got: " + percent);
    }
    this.percent = percent;
}

IllegalStateException

// Cause: method called at wrong time/state
// Use when object is in wrong state for operation

public void start() {
    if (running) {
        throw new IllegalStateException("Already running");
    }
    running = true;
}

public void next() {
    if (!hasNext()) {
        throw new IllegalStateException("No more elements");
    }
    // return next element
}

UnsupportedOperationException

// Cause: operation not supported
List<String> immutable = List.of("a", "b", "c");
immutable.add("d");  // UnsupportedOperationException

// Throw in your code for unimplemented methods
public void optionalFeature() {
    throw new UnsupportedOperationException("Not implemented");
}

ConcurrentModificationException

// Cause: modifying collection while iterating
List<String> list = new ArrayList<>(List.of("a", "b", "c"));
for (String s : list) {
    list.remove(s);  // ConcurrentModificationException
}

// Solution 1: Use Iterator.remove()
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    if (condition) {
        it.remove();  // Safe
    }
}

// Solution 2: Use removeIf()
list.removeIf(s -> s.equals("b"));

// Solution 3: Collect items to remove, then remove
List<String> toRemove = new ArrayList<>();
for (String s : list) {
    if (condition) toRemove.add(s);
}
list.removeAll(toRemove);

IOException

// Cause: I/O operation failure
// Subclasses: FileNotFoundException, EOFException, etc.

try {
    String content = Files.readString(Path.of("missing.txt"));
} catch (NoSuchFileException e) {
    System.out.println("File doesn't exist: " + e.getFile());
} catch (IOException e) {
    System.out.println("IO error: " + e.getMessage());
}

FileNotFoundException

// Cause: file doesn't exist or can't be opened
try {
    FileReader reader = new FileReader("missing.txt");
} catch (FileNotFoundException e) {
    System.out.println("File not found: " + e.getMessage());
}

// Prevention: check first
File file = new File("data.txt");
if (file.exists() && file.canRead()) {
    // safe to open
}

Creating Custom Exceptions

Unchecked Exception

public class InvalidOrderException extends RuntimeException {
    
    private final String orderId;
    
    public InvalidOrderException(String message, String orderId) {
        super(message);
        this.orderId = orderId;
    }
    
    public InvalidOrderException(String message, String orderId, Throwable cause) {
        super(message, cause);
        this.orderId = orderId;
    }
    
    public String getOrderId() {
        return orderId;
    }
}

// Usage
throw new InvalidOrderException("Order total cannot be negative", "ORD-123");

Checked Exception

public class InsufficientFundsException extends Exception {
    
    private final double requested;
    private final double available;
    
    public InsufficientFundsException(double requested, double available) {
        super(String.format("Requested %.2f but only %.2f available", 
              requested, available));
        this.requested = requested;
        this.available = available;
    }
    
    public double getRequested() { return requested; }
    public double getAvailable() { return available; }
}

// Usage - must be declared or caught
public void withdraw(double amount) throws InsufficientFundsException {
    if (amount > balance) {
        throw new InsufficientFundsException(amount, balance);
    }
    balance -= amount;
}

Exception Handling Patterns

Wrap and Rethrow

public void processFile(String path) throws ProcessingException {
    try {
        String content = Files.readString(Path.of(path));
        // process content
    } catch (IOException e) {
        // Wrap low-level exception in domain exception
        throw new ProcessingException("Failed to process " + path, e);
    }
}

Log and Rethrow

public void process() throws ServiceException {
    try {
        // risky operation
    } catch (Exception e) {
        logger.error("Processing failed", e);
        throw e;  // or wrap in ServiceException
    }
}

Convert to Unchecked

// In lambdas where checked exceptions are inconvenient
list.stream()
    .map(path -> {
        try {
            return Files.readString(Path.of(path));
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    })
    .collect(Collectors.toList());

Provide Default Value

public String readFileOrDefault(String path, String defaultValue) {
    try {
        return Files.readString(Path.of(path));
    } catch (IOException e) {
        return defaultValue;
    }
}

// With Optional
public Optional<String> readFile(String path) {
    try {
        return Optional.of(Files.readString(Path.of(path)));
    } catch (IOException e) {
        return Optional.empty();
    }
}

Retry Pattern

public String fetchWithRetry(String url, int maxAttempts) throws IOException {
    IOException lastException = null;
    
    for (int attempt = 1; attempt <= maxAttempts; attempt++) {
        try {
            return fetch(url);
        } catch (IOException e) {
            lastException = e;
            System.out.println("Attempt " + attempt + " failed, retrying...");
            try {
                Thread.sleep(1000 * attempt);  // Exponential backoff
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                throw new IOException("Interrupted during retry", ie);
            }
        }
    }
    
    throw new IOException("Failed after " + maxAttempts + " attempts", lastException);
}

Exception Information Methods

try {
    // risky code
} catch (Exception e) {
    // Get message
    String msg = e.getMessage();
    
    // Get localized message
    String localMsg = e.getLocalizedMessage();
    
    // Get cause (wrapped exception)
    Throwable cause = e.getCause();
    
    // Get stack trace
    StackTraceElement[] stack = e.getStackTrace();
    
    // Print stack trace to stderr
    e.printStackTrace();
    
    // Print to specific stream
    e.printStackTrace(System.out);
    
    // Get stack trace as string
    StringWriter sw = new StringWriter();
    e.printStackTrace(new PrintWriter(sw));
    String stackTrace = sw.toString();
}

Best Practices

Do

// Catch specific exceptions
try {
    // code
} catch (FileNotFoundException e) {
    // handle specifically
}

// Include context in messages
throw new IllegalArgumentException("User ID must be positive, got: " + userId);

// Clean up resources with try-with-resources
try (Connection conn = getConnection()) {
    // use connection
}

// Preserve the cause chain
throw new ServiceException("Failed to process order", originalException);

// Use standard exceptions when appropriate
throw new IllegalArgumentException("Invalid input");
throw new IllegalStateException("Not initialized");
throw new UnsupportedOperationException("Not implemented");

Don’t

// Don't catch Exception or Throwable broadly
try {
    // code
} catch (Exception e) {  // Too broad
    // might hide programming errors
}

// Don't swallow exceptions silently
try {
    // code
} catch (Exception e) {
    // Nothing here - bad!
}

// Don't use exceptions for control flow
try {
    while (true) {
        array[i++];  // Don't rely on ArrayIndexOutOfBoundsException
    }
} catch (ArrayIndexOutOfBoundsException e) {
    // finished iteration - bad pattern
}

// Don't throw Exception or Throwable directly
throw new Exception("Error");  // Too generic

Quick Reference Table

Exception Type Common Cause
NullPointerException Unchecked Method call on null
ArrayIndexOutOfBoundsException Unchecked Invalid array index
ClassCastException Unchecked Invalid type cast
NumberFormatException Unchecked Invalid number parsing
IllegalArgumentException Unchecked Invalid method argument
IllegalStateException Unchecked Wrong object state
UnsupportedOperationException Unchecked Operation not supported
ConcurrentModificationException Unchecked Collection modified during iteration
IOException Checked I/O operation failure
FileNotFoundException Checked File doesn’t exist
SQLException Checked Database error
ClassNotFoundException Checked Class not found at runtime
InterruptedException Checked Thread interrupted

Related: Java Exception Handling | Reading and Writing Files in Java | Java Collections Cheat Sheet

Sources

  • Oracle. “Lesson: Exceptions.” docs.oracle.com/javase/tutorial/essential/exceptions
  • Oracle. “java.lang Package.” docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/package-summary.html
Scroll to Top