00:00

Types of Exceptions in Java – Explained with Examples

Java groups its exceptions into a few families, and knowing them tells you a lot: whether the compiler will force you to handle a problem, whether it usually means a bug in your code, and whether recovery is possible at all. This tutorial explains the three main categories, checked exceptions, unchecked exceptions and errors, shows the most common built-in exceptions in action, and introduces user-defined exceptions.

1. The Main Categories

Exception families
Throwable
 ├─ Error                          (unchecked) serious JVM / environment problems
 └─ Exception
     ├─ checked exceptions         IOException, SQLException, InterruptedException ...
     └─ RuntimeException           (unchecked) NullPointerException, ArithmeticException ...
CategoryExtendsMust be caught or declared?Usually means
Checked exceptionException (not RuntimeException)Yes, enforced by the compilerAn expected problem outside your control (file, network, database)
Unchecked exceptionRuntimeExceptionNoA programming bug or invalid input
ErrorErrorNoA serious problem the application usually cannot fix

You can also divide exceptions into built-in exceptions provided by Java and user-defined (custom) exceptions you create yourself.

2. Unchecked Exceptions (Runtime Exceptions)

Unchecked exceptions are subclasses of RuntimeException. The compiler does not force you to handle them because they usually signal mistakes that should be fixed in the code, not caught. Here are the most common ones, each triggered on purpose:

CommonUnchecked.java
import java.util.List;

public class CommonUnchecked {
    static String missing = null;

    static void attempt(String label, Runnable action) {
        try {
            action.run();
        } catch (RuntimeException e) {
            System.out.printf("%-28s -> %s: %s%n", label, e.getClass().getSimpleName(), shorten(e.getMessage()));
        }
    }

    static String shorten(String msg) {            // keep long JDK messages readable
        return msg != null && msg.contains(" (") ? msg.substring(0, msg.indexOf(" (")) : msg;
    }

    public static void main(String[] args) {
        Object number = 42;
        int[] arr = new int[2];

        attempt("missing.length()", () -> missing.length());
        attempt("10 / 0", () -> System.out.println(10 / 0));
        attempt("arr[5]", () -> System.out.println(arr[5]));
        attempt("\"abc\".charAt(7)", () -> "abc".charAt(7));
        attempt("Integer.parseInt(\"12a\")", () -> Integer.parseInt("12a"));
        attempt("(String) number", () -> System.out.println((String) number));
        attempt("List.of(1).add(2)", () -> List.of(1).add(2));
        attempt("new int[-1]", () -> System.out.println(new int[-1].length));
    }
}
Output
missing.length()             -> NullPointerException: Cannot invoke "String.length()" because "CommonUnchecked.missing" is null
10 / 0                       -> ArithmeticException: / by zero
arr[5]                       -> ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 2
"abc".charAt(7)              -> StringIndexOutOfBoundsException: Index 7 out of bounds for length 3
Integer.parseInt("12a")      -> NumberFormatException: For input string: "12a"
(String) number              -> ClassCastException: class java.lang.Integer cannot be cast to class java.lang.String
List.of(1).add(2)            -> UnsupportedOperationException: null
new int[-1]                  -> NegativeArraySizeException: -1
ExceptionCauseHow to avoid it
NullPointerExceptionUsing a null referenceInitialise variables, check for null, use Optional
ArithmeticExceptionInteger division by zeroCheck the divisor first
ArrayIndexOutOfBoundsExceptionIndex outside 0…length-1Loop with i < arr.length
StringIndexOutOfBoundsExceptionInvalid index into a stringCheck length() first
NumberFormatExceptionParsing invalid numeric textValidate input, catch around parsing
ClassCastExceptionInvalid castUse instanceof pattern matching
UnsupportedOperationExceptionModifying an unmodifiable collectionCopy into a modifiable collection
IllegalArgumentExceptionA method received an invalid argumentValidate arguments before calling
IllegalStateExceptionMethod called at the wrong timeFollow the object's life cycle
ConcurrentModificationExceptionChanging a collection while iteratingUse removeIf() or an iterator

3. Checked Exceptions

Checked exceptions represent problems that can happen even in correct code: a file may be missing, a server may be down, a thread may be interrupted. Java requires every method that might throw one to either catch it or declare it with throws; otherwise the code does not compile.

CommonChecked.java
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;

public class CommonChecked {
    public static void main(String[] args) {
        // Checked: the compiler forces us to handle (or declare) these
        try (FileReader reader = new FileReader("no-such-file.txt")) {
            System.out.println("opened");
        } catch (IOException e) {
            System.out.println("IOException family -> " + e.getClass().getSimpleName() + ": " + e.getMessage());
        }

        try {
            new URI("http://bad host/");
        } catch (URISyntaxException e) {
            System.out.println("URISyntaxException -> " + e.getMessage());
        }

        try {
            Thread.sleep(10);
            System.out.println("InterruptedException must be handled around Thread.sleep()");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // Unchecked: handling is optional
        try {
            LocalDate.parse("2026-13-40");
        } catch (DateTimeParseException e) {
            System.out.println("DateTimeParseException (unchecked) -> " + e.getMessage());
        }
    }
}
Output
IOException family -> FileNotFoundException: no-such-file.txt (No such file or directory)
URISyntaxException -> Illegal character in authority at index 10: http://bad host/
InterruptedException must be handled around Thread.sleep()
DateTimeParseException (unchecked) -> Text '2026-13-40' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 13
Checked exceptionTypical source
IOException, FileNotFoundExceptionFiles, streams, sockets
SQLExceptionJDBC database access
InterruptedExceptionThread.sleep(), join(), blocking queues
ClassNotFoundExceptionLoading a class by name
URISyntaxException, MalformedURLExceptionBuilding URIs and URLs
CloneNotSupportedExceptionObject.clone()

Note that DateTimeParseException is unchecked even though it is about input; newer APIs often prefer unchecked exceptions. Learn more in Checked vs Unchecked Exceptions.

4. Errors

Errors are thrown by the JVM when something is seriously wrong with the runtime environment. Applications normally should not catch them, because there is little they can do to recover:

ErrorExamples.java
public class ErrorExamples {
    static int depth = 0;
    static void recurse() { depth++; recurse(); }

    public static void main(String[] args) {
        try {
            recurse();                                   // no base case
        } catch (StackOverflowError e) {
            System.out.println("StackOverflowError after many nested calls (an Error, not an Exception)");
        }
        System.out.println("StackOverflowError is an Exception? " + (Exception.class.isAssignableFrom(StackOverflowError.class)));
        System.out.println("OutOfMemoryError is a Throwable?     " + (Throwable.class.isAssignableFrom(OutOfMemoryError.class)));
    }
}
Output
StackOverflowError after many nested calls (an Error, not an Exception)
StackOverflowError is an Exception? false
OutOfMemoryError is a Throwable?     true
  • OutOfMemoryError: the heap is full.
  • StackOverflowError: too many nested method calls, usually endless recursion.
  • NoClassDefFoundError: a class available at compile time is missing at runtime.
  • ExceptionInInitializerError: a static initializer threw an exception.
  • AssertionError: an assert statement failed.

See Error vs Exception.

5. User-Defined (Custom) Exceptions

When built-in exceptions do not describe a problem precisely, create your own by extending Exception (checked) or RuntimeException (unchecked):

InsufficientBalanceException.java
public class InsufficientBalanceException extends RuntimeException {
    public InsufficientBalanceException(double needed, double available) {
        super("Need " + needed + " but only " + available + " is available");
    }
}

A full guide is in Custom Exception in Java.

6. Which Type Should Your Code Throw?

  • Invalid arguments: IllegalArgumentException or NullPointerException (via Objects.requireNonNull).
  • Calling a method at the wrong time: IllegalStateException.
  • Unsupported operations: UnsupportedOperationException.
  • Domain-specific problems: a custom exception with a clear name.
  • Recoverable external failures that callers must handle: a checked exception (or a well-documented unchecked one).
  • Never throw Error types yourself, except AssertionError for impossible situations.

7. Summary

  • Java exceptions are checked exceptions, unchecked (runtime) exceptions, and errors.
  • Checked exceptions must be caught or declared; unchecked exceptions and errors need not be.
  • Unchecked exceptions usually reveal bugs; checked exceptions represent expected external failures.
  • Errors indicate serious JVM problems and are normally not caught.
  • Create custom exceptions for application-specific problems.

Related Tutorials