00:00

Multiple catch Blocks in Java – Explained with Examples

Last updated: 6 min read

One block of code can fail in several different ways. Reading a value from an array and dividing it might fail because the index is wrong, the text is not a number, or the divisor is zero. Multiple catch blocks let you handle each kind of failure differently, and Java 7's multi-catch lets you handle several kinds the same way in one block.

This tutorial explains how Java chooses a catch block, why their order matters, how to use multi-catch, and the rules the compiler enforces.

1. Syntax

Multiple catch blocks
try {
    // risky code
} catch (ExceptionTypeA e) {
    // handle A
} catch (ExceptionTypeB e) {
    // handle B
} catch (ExceptionTypeC | ExceptionTypeD e) {   // multi-catch (Java 7+)
    // handle C and D the same way
}
Flow of a try block with multiple catch blocks

2. Handling Each Exception Differently

MultipleCatch.java
public class MultipleCatch {
    static void process(String[] data, int index, int divisor) {
        try {
            int value = Integer.parseInt(data[index]);
            System.out.println(data[index] + " / " + divisor + " = " + value / divisor);
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("No item at index " + index);
        } catch (NumberFormatException e) {
            System.out.println("'" + data[index] + "' is not a number");
        } catch (ArithmeticException e) {
            System.out.println("Cannot divide by zero");
        }
    }

    public static void main(String[] args) {
        String[] data = {"100", "abc", "60"};
        process(data, 0, 4);
        process(data, 5, 4);
        process(data, 1, 4);
        process(data, 2, 0);
    }
}
Output
100 / 4 = 25
No item at index 5
'abc' is not a number
Cannot divide by zero

Only one catch block runs per exception: Java checks the catch blocks from top to bottom and runs the first one whose type matches. The others are skipped.

3. Why the Order of catch Blocks Matters

A catch block also matches all subclasses of its type. If a general type comes first, it catches everything and the specific blocks below can never run. So always order catch blocks from most specific to most general:

OrderMatters.java
public class OrderMatters {
    public static void main(String[] args) {
        Object[] samples = {null, "text", 42};
        for (Object s : samples) {
            try {
                Integer n = (Integer) s;
                System.out.println("number: " + (n * 2));
            } catch (NullPointerException e) {          // specific types first
                System.out.println("null value");
            } catch (ClassCastException e) {
                System.out.println("not a number: " + s);
            } catch (RuntimeException e) {               // general fallback last
                System.out.println("other problem: " + e);
            }
        }
    }
}
Output
null value
not a number: text
number: 84

Writing catch (RuntimeException e) above catch (ClassCastException e) would not compile, because the second block would be unreachable ("exception ClassCastException has already been caught").

4. Multi-catch (Java 7+)

When several exception types need the same handling, list them in one catch block separated by |. This removes duplicated code:

MultiCatch.java
import java.time.LocalDate;
import java.time.format.DateTimeParseException;

public class MultiCatch {
    static void parseOrder(String line) {
        try {
            String[] p = line.split(";");
            int qty = Integer.parseInt(p[0]);
            LocalDate date = LocalDate.parse(p[1]);
            System.out.println("ok: " + qty + " on " + date);
        } catch (NumberFormatException | DateTimeParseException e) {   // same handling for both
            System.out.println("bad data in '" + line + "': " + e.getClass().getSimpleName());
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("missing field in '" + line + "'");
        }
    }

    public static void main(String[] args) {
        parseOrder("3;2026-10-11");
        parseOrder("three;2026-10-11");
        parseOrder("3;2026-02-30");
        parseOrder("3");
    }
}
Output
ok: 3 on 2026-10-11
bad data in 'three;2026-10-11': NumberFormatException
bad data in '3;2026-02-30': DateTimeParseException
missing field in '3'

Multi-catch rules

  • The types in a multi-catch must not be related by inheritance. If one is a subclass of another, just catch the parent:
javac output
Bad.java:3: error: Alternatives in a multi-catch statement cannot be related by subclassing
 catch (NumberFormatException | IllegalArgumentException e) { }
                                ^
  Alternative NumberFormatException is a subclass of alternative IllegalArgumentException
  • The catch variable is implicitly final; you cannot assign a new value to it.
  • Inside the block, the variable's type is the closest common supertype, so you can only call methods available on it (for example getMessage()).
  • Rethrowing it with throw e; is allowed, and the compiler still knows the precise types that can be thrown.

5. Separate catch Blocks or Multi-catch?

Use separate catch blocks when…Use multi-catch when…
Each exception needs a different responseSeveral exceptions need exactly the same response
Exceptions are related by inheritance (order them)The exceptions are unrelated types
You need the specific type's methodsCommon methods like getMessage() are enough

6. Tips

  • Do not catch exceptions you cannot handle meaningfully; let them propagate.
  • A final catch (Exception e) as a fallback is acceptable at the top level of an application, but log it.
  • Keep each catch block short; move complex recovery into methods.
  • Combine with finally or try-with-resources for clean-up that must always happen.

7. Summary

  • A try block can be followed by several catch blocks for different exception types.
  • Java runs only the first catch whose type matches, checking from top to bottom.
  • Order catch blocks from specific to general; otherwise the compiler reports unreachable code.
  • Multi-catch (catch (A | B e)) handles unrelated exception types in one block.
  • The multi-catch variable is final, and the types cannot be subclasses of one another.

Related Tutorials