Before Java 7, we had to write multiple exception handling codes for different types of exceptions even if there was code redundancy.
Let's take an example.
Example 1: Multiple catch blocks
class Main {
  public static void main(String[] args) {
    try {
      int array[] = new int[10];
      array[10] = 30 / 0;
    } catch (ArithmeticException e) {
      System.out.println(e.getMessage());
    } catch (ArrayIndexOutOfBoundsException e) {
      System.out.println(e.getMessage());
    } 
  }
}
Output
/ by zero
In this example, two exceptions may occur:
ArithmeticExceptionbecause we are trying to divide a number by 0.ArrayIndexOutOfBoundsExceptionbecause we have declared a new integer array with array bounds 0 to 9 and we are trying to assign a value to index 10.
We are printing out the exception message in both the catch blocks i.e. duplicate code.
The associativity of the assignment operator = is right to left, so an ArithmeticException is thrown first with the message / by zero.
Handle Multiple Exceptions in a catch Block
In Java SE 7 and later, we can now catch more than one type of exception in a single catch block.
Each exception type that can be handled by the catch block is separated using a vertical bar or pipe |.
Its syntax is:
try {
  // code
} catch (ExceptionType1 | Exceptiontype2 ex) { 
  // catch block
}
Example 2: Multi-catch block
class Main {
  public static void main(String[] args) {
    try {
      int array[] = new int[10];
      array[10] = 30 / 0;
    } catch (ArithmeticException | ArrayIndexOutOfBoundsException e) {
      System.out.println(e.getMessage());
    }
  }
}
Output
/ by zero
Catching multiple exceptions in a single catch block reduces code duplication and increases efficiency.
The bytecode generated while compiling this program will be smaller than the program having multiple catch blocks as there is no code redundancy.
Note: If a catch block handles multiple exceptions, the catch parameter is implicitly final. This means we cannot assign any values to catch parameters.
Catching base Exception
When catching multiple exceptions in a single catch block, the rule is generalized to specialized.
This means that if there is a hierarchy of exceptions in the catch block, we can catch the base exception only instead of catching multiple specialized exceptions.
Let's take an example.
Example 3: Catching base exception class only
class Main {
  public static void main(String[] args) {
    try {
      int array[] = new int[10];
      array[10] = 30 / 0;
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }
}
Output
/ by zero
We know that all the exception classes are subclasses of the Exception class. So, instead of catching multiple specialized exceptions, we can simply catch the Exception class.
If the base exception class has already been specified in the catch block, do not use child exception classes in the same catch block. Otherwise, we will get a compilation error.
Let's take an example.
Example 4: Catching base and child exception classes
class Main {
  public static void main(String[] args) {
    try {
      int array[] = new int[10];
      array[10] = 30 / 0;
    } catch (Exception | ArithmeticException | ArrayIndexOutOfBoundsException e) {
      System.out.println(e.getMessage());
    }
  }
}
Output
Main.java:6: error: Alternatives in a multi-catch statement cannot be related by subclassing
In this example, ArithmeticException and ArrayIndexOutOfBoundsException are both subclasses of the Exception class. So, we get a compilation error.
Also Read: