Множественные операторы catch

В некоторых случаях один фрагмент кода может инициировать более одного исключения. Чтобы справиться с такой ситуацией, вы можете специфицировать два или более операторов catch, каждый для перехвата своего типа исключений. Когда возбуждается исключение, каждый оператор catch проверяется по порядку, и первый из них, чей тип соответствует исключению, выполняется. После того, как выполнится один из операторов catch, все остальные пропускаются, и выполнение программы продолжается с места, следующего за блоком try/catch. В следующем примере кода перехватываются два разных типа исключений.

// Демонстрация применения множественных операторов catch.
class MultiCatch {
public static void main(String args[]) { try {
int a = args.length;
System.out.println("a = " + a);
int b = 42 / a;
int c[] = { 1 };
с[42] = 99; } catch(ArithmeticException e) {
System.out.println("Деление на 0: " + e);
}
catch(ArraylndexOutOfBoundsException e) {
System.out.println("Ошибка индекса массива: " + e) ;
}
System.out.println("После блока try/catch.");
}
}

Эта программа вызовет исключение деления на ноль, если будет запущена без аргументов командной строки, поскольку в этом случае а будет равно 0. Она выполнит деление, если будут передан аргумент командной строки, устанавливающий а равным значению больше нуля. Но в этом случае будет сгенерировано исключение Arraylnde xOutOfBoundsException, так как длина массива целых чисел с равна 1, в то время как программа пытается присвоить значение элементу массива с [ 42 ].

Вот результаты запуска этой программы обоими способами:

C:\>java MultiCatch а = 0
Деление на 0: java.lang.ArithmeticException: / by zero После блока try/oatch.
С:\>java MultiCatch TestArg a = 1
Ошибка индекса массива: java.lang.ArraylndexOutOfBoundsException:42
После блока try/catch.

Когда используются множественные операторы catch, важно помнить, что подклассы исключений должны следовать перед любыми их суперклассами. Это потому, что оператор catch, который использует суперкласс, будет перехватывать все исключения этого суперкласса плюс всех его подклассов. То есть подкласс исключения никогда не будет обработан, если вы попытаетесь его перехватить после его суперкласса. Более того, в Java недостижимый код является ошибкой. Например, рассмотрим следующую программу:

/* Эта программа содержит ошибку.
Подкласс должен идти перед его суперклассом в
последовательности операторов catch. В противном случае
будет создан недоступный код, что приведет к ошибке при компиляции.
*/ class SuperSubCatch {
public static void main(String args[]) {
try ( int a = 0; int b = 42 / a;
}
catch(Exception e) {
System.out.println ("Общий перехват Exception.");
}
/* Этот catch никогда не будет достигнут, потому что
ArithmeticException — это подкласс Exception. */
catch(ArithmeticException е) {
// Ошибка — недостижимый код
System.out.println("Это никогда не выполнится.");
}
}

Если вы попытаетесь скомпилировать эту программу, то получите сообщение об ошибке, говорящее о том, что второй оператор catch недостижим, потому что исключение уже перехвачено. Поскольку ArithmeticException — подкласс Exception, первый оператор catch обработает все ошибки, основанные на Exception, включая ArithmeticException. Это означает, что второй оператор catch не будет никогда выполнен. Чтобы исправить эту проблему, потребуется изменить порядок следования операторов catch.