Java Cheatsheet

Exceptions

Use this Java reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Exception Hierarchy

Throwable
├── Error              — JVM-level, don't catch (OutOfMemoryError, StackOverflowError)
└── Exception
    ├── RuntimeException (unchecked — no throws declaration required)
    │   ├── NullPointerException
    │   ├── ArrayIndexOutOfBoundsException
    │   ├── ClassCastException
    │   ├── IllegalArgumentException
    │   ├── IllegalStateException
    │   ├── ArithmeticException
    │   ├── NumberFormatException
    │   ├── UnsupportedOperationException
    │   ├── IndexOutOfBoundsException
    │   └── ConcurrentModificationException
    └── (checked — must be declared or caught)
        ├── IOException
        │   ├── FileNotFoundException
        │   └── EOFException
        ├── SQLException
        ├── ParseException
        ├── InterruptedException
        └── CloneNotSupportedException

try / catch / finally

try {
    int result = 10 / 0;
    String s = null;
    s.length();                        // NullPointerException
} catch (ArithmeticException e) {
    System.out.println("Math error: " + e.getMessage());
} catch (NullPointerException e) {
    System.out.println("Null: " + e.getMessage());
} catch (Exception e) {
    // Broad catch-all (avoid if possible)
    e.printStackTrace();
} finally {
    System.out.println("Always runs — good for cleanup");
}

Order matters: catch subclass before superclass. Catching Exception first would cause compile errors for subsequent specific catches.

Multi-catch (Java 7+)

try {
    methodThatMayThrow();
} catch (IOException | SQLException e) {
    // e is effectively final here
    System.out.println("I/O or SQL error: " + e.getMessage());
}

try-with-resources (Java 7+)

Resources implementing AutoCloseable are automatically closed, even if an exception is thrown.

try (FileReader fr = new FileReader("file.txt");
     BufferedReader br = new BufferedReader(fr)) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}
// fr and br are closed in reverse order automatically

// Java 9+: effectively-final variable from outer scope
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try (br) {                     // no redeclare needed
    br.readLine();
}

Throwing Exceptions

// Throw an existing exception
throw new IllegalArgumentException("Value must be positive: " + value);

// Re-throw
try {
    riskyMethod();
} catch (IOException e) {
    throw e;                                    // re-throw same exception
}

// Wrap in a different exception (exception chaining)
try {
    riskyMethod();
} catch (IOException e) {
    throw new RuntimeException("Failed to process", e);  // cause preserved
}

// throw in a method — checked exceptions must be declared
public void readFile(String path) throws IOException {
    throw new FileNotFoundException("Not found: " + path);
}

Custom Exceptions

// Unchecked custom exception
public class ValidationException extends RuntimeException {
    private final String field;

    public ValidationException(String field, String message) {
        super(message);
        this.field = field;
    }

    // Preserve cause
    public ValidationException(String field, String message, Throwable cause) {
        super(message, cause);
        this.field = field;
    }

    public String getField() { return field; }
}

// Checked custom exception
public class ServiceException extends Exception {
    private final int errorCode;

    public ServiceException(int errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }

    public ServiceException(int errorCode, String message, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
    }

    public int getErrorCode() { return errorCode; }
}

// Usage
if (age < 0) throw new ValidationException("age", "Age cannot be negative");

Checked vs. Unchecked

CheckedUnchecked (RuntimeException)
Must declare with throwsNo declaration required
Caller must catch or propagateCaller can ignore
Represents recoverable failuresRepresents programming errors
IOException, SQLExceptionNullPointerException, IllegalArgumentException
// Checked — must declare
public String readFile(String path) throws IOException {
    return Files.readString(Path.of(path));
}

// Unchecked — no declaration needed
public int divide(int a, int b) {
    if (b == 0) throw new ArithmeticException("Division by zero");
    return a / b;
}

Exception Methods (Throwable API)

try {
    throw new RuntimeException("something broke");
} catch (Exception e) {
    e.getMessage()             // "something broke"
    e.getLocalizedMessage()    // same (can be overridden for locale)
    e.getCause()               // the wrapped cause, or null
    e.getClass().getName()     // "java.lang.RuntimeException"
    e.printStackTrace()        // prints stack trace to stderr
    e.getStackTrace()          // StackTraceElement[]
    String trace = Arrays.toString(e.getStackTrace());
}

Suppressed Exceptions (Java 7+)

When an exception is thrown in a finally block (or auto-close), it can suppress the original.

Exception primary = new Exception("primary");
Exception suppressed = new Exception("suppressed");
primary.addSuppressed(suppressed);

try {
    throw primary;
} catch (Exception e) {
    Throwable[] suppressed = e.getSuppressed(); // [suppressed]
}

// try-with-resources handles this automatically:
// if body throws AND close() throws, close's exception is suppressed

NullPointerException Helpers (Java 14+)

String s = null;
try {
    System.out.println(s.length());
} catch (NullPointerException e) {
    // Java 14+ helpful NPE messages:
    // "Cannot invoke "String.length()" because "s" is null"
    System.out.println(e.getMessage());
}

// Avoid NPE with Objects utilities
Objects.requireNonNull(arg, "arg must not be null");  // throws NPE with message
Objects.requireNonNullElse(s, "default");
Objects.requireNonNullElseGet(s, () -> computeDefault());
Objects.isNull(s)      // true
Objects.nonNull(s)     // false

Best Practices

// Catch specific, not broad
try { ... } catch (IOException e) { ... }  // good
try { ... } catch (Exception e)  { ... }  // too broad — hides bugs

// Never swallow exceptions silently
catch (Exception e) { }                    // BAD — swallowed!
catch (Exception e) { log.error(e); }     // acceptable minimum

// Exception chaining — always preserve cause
throw new ServiceException(500, "DB failed", cause);  // not just message

// Use finally or try-with-resources to release resources
// — never rely on GC for file handles, connections, etc.

// Prefer standard exceptions over custom when appropriate:
// IllegalArgumentException — bad argument
// IllegalStateException   — wrong object state
// NullPointerException    — null where non-null expected
// IndexOutOfBoundsException — index out of valid range
// UnsupportedOperationException — operation not supported
// NoSuchElementException  — requested element does not exist
// ConcurrentModificationException — structural change during iteration

assert vs. Exceptions

// assert — for internal invariants (disabled in production)
assert x > 0 : "x must be positive";

// exceptions — for user/caller input validation (always active)
if (x <= 0) throw new IllegalArgumentException("x must be positive");

Stack Overflow and OOM

// StackOverflowError — infinite recursion
void recurse() { recurse(); }  // throws StackOverflowError

// OutOfMemoryError — heap exhausted
// Don't try to catch Error in general — the JVM state is unreliable
// Exception: specific scenarios like OOM where you can free resources:
try {
    allocateBigArray();
} catch (OutOfMemoryError e) {
    clearCache();  // release some memory, then rethrow or degrade gracefully
    throw e;
}