JavaScript: Исключения. JavaScript: Исключения Обработка исключений и условные конструкции

The try...catch statement marks a block of statements to try, and specifies a response, should an exception be thrown.

The source for this interactive example is stored in a GitHub repository. If you"d like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.

Syntax

try { try_statements } ... try_statements The statements to be executed. catch_statements_1 , catch_statements_2 Statements that are executed if an exception is thrown in the try -block. exception_var_1 , exception_var_2 An identifier to hold an exception object for the associated catch -block. condition_1 A conditional expression. finally_statements Statements that are executed after the try statement completes. These statements execute regardless of whether an exception was thrown or caught.

Description

The try statement consists of a try -block, which contains one or more statements. {} must always be used, even for single statements. At least one catch -block, or a finally -block, must be present. This gives us three forms for the try statement:

  • try...catch
  • try...finally
  • try...catch...finally

A catch -block contains statements that specify what to do if an exception is thrown in the try -block. If any statement within the try -block (or in a function called from within the try -block) throws an exception, control is immediately shifted to the catch -block. If no exception is thrown in the try -block, the catch -block is skipped.

The finally -block will always execute after the try -block and catch -block(s) have finished executing. It always executes, regardless of whether an exception was thrown or caught.

You can nest one or more try statements. If an inner try statement does not have a catch -block, the enclosing try statement"s catch -block is used instead.

You can also use the try statement to handle JavaScript exceptions. See the JavaScript Guide for more information on JavaScript exceptions.

Unconditional catch-block

When a catch -block is used, the catch -block is executed when any exception is thrown from within the try -block. For example, when the exception occurs in the following code, control transfers to the catch -block.

Try { throw "myException"; // generates an exception } catch (e) { // statements to handle any exceptions logMyErrors(e); // pass exception object to error handler }

The catch -block specifies an identifier (e in the example above) that holds the value of the exception; this value is only available in the scope of the catch -block.

Conditional catch-blocks

Non-standard
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future.

You can also use one or more conditional catch -blocks to handle specific exceptions. In this case, the appropriate catch -block is entered when the specified exception is thrown. In the following example, code in the try -block can potentially throw three exceptions: TypeError , RangeError , and EvalError . When an exception occurs, control transfers to the appropriate catch -block. If the exception is not one of the specified exceptions and an unconditional catch -block is found, control transfers to that catch -block.

If you use an unconditional catch -block with one or more conditional catch -blocks, the unconditional catch -block must be specified last. Otherwise, the unconditional catch -block will intercept all types of exception before they can reach the conditional ones.

Reminder: this functionality is not part of the ECMAScript specification and has been removed in Firefox 59. It"s not supported in any current browser anymore.

Try { myroutine(); // may throw three types of exceptions } catch (e if e instanceof TypeError) { // statements to handle TypeError exceptions } catch (e if e instanceof RangeError) { // statements to handle RangeError exceptions } catch (e if e instanceof EvalError) { // statements to handle EvalError exceptions } catch (e) { // statements to handle any unspecified exceptions logMyErrors(e); // pass exception object to error handler }

Here is the same "Conditional catch -blocks" using code that conforms to ECMAScript specification (obviously it"s verbose, but works everywhere):

Try { myroutine(); // may throw three types of exceptions } catch (e) { if (e instanceof TypeError) { // statements to handle TypeError exceptions } else if (e instanceof RangeError) { // statements to handle RangeError exceptions } else if (e instanceof EvalError) { // statements to handle EvalError exceptions } else { // statements to handle any unspecified exceptions logMyErrors(e); // pass exception object to error handler } }

One reason for using the old conditional try-block is for only catching (and silencing) a small subset of expected errors. You can instead re-throw the error if you want this behavior:

Try { myRoutine(); } catch (e) { if (e instanceof RangeError) { // statements to handle this very common expected error } else { throw e; // re-throw the error unchanged } }

The exception identifier

When an exception is thrown in the try -block, exception_var (i.e., the e in catch (e)) holds the exception value. You can use this identifier to get information about the exception that was thrown. This identifier is only available in the catch -block"s scope .

Function isValidJSON(text) { try { JSON.parse(text); return true; } catch { return false; } }

The finally-block

The finally -block contains statements to execute after the try -block and catch -block(s) execute, but before the statements following the try...catch...finally -block. Note that the finally -block executes regardless of whether an exception is thrown. Also, if an exception is thrown, the statements in the finally -block execute even if no catch -block handles the exception.

The following example shows one use case for the finally -block. The code opens a file and then executes statements that use the file; the finally -block makes sure the file always closes after it is used even if an exception was thrown.

OpenMyFile(); try { // tie up a resource writeMyFile(theData); } finally { closeMyFile(); // always close the resource }

Examples

Nested try-blocks

First, let"s see what happens with this:

Try { try { throw new Error("oops"); } finally { console.log("finally"); } } catch (ex) { console.error("outer", ex.message); } // Output: // "finally" // "outer" "oops"

Now, if we already caught the exception in the inner try -block by adding a catch -block

Try { try { throw new Error("oops"); } catch (ex) { console.error("inner", ex.message); } finally { console.log("finally"); } } catch (ex) { console.error("outer", ex.message); } // Output: // "inner" "oops" // "finally"

And now, let"s rethrow the error.

Try { try { throw new Error("oops"); } catch (ex) { console.error("inner", ex.message); throw ex; } finally { console.log("finally"); } } catch (ex) { console.error("outer", ex.message); } // Output: // "inner" "oops" // "finally" // "outer" "oops"

Any given exception will be caught only once by the nearest enclosing catch -block unless it is rethrown. Of course, any new exceptions raised in the "inner" block (because the code in catch -block may do something that throws), will be caught by the "outer" block.

Returning from a finally-block

If the finally -block returns a value, this value becomes the return value of the entire try-catch-finally statement, regardless of any return statements in the try and catch -blocks. This includes exceptions thrown inside of the catch -block:

(function() { try { try { throw new Error("oops"); } catch (ex) { console.error("inner", ex.message); throw ex; } finally { console.log("finally"); return; } } catch (ex) { console.error("outer", ex.message); } })(); // Output: // "inner" "oops" // "finally"

The outer "oops" is not thrown because of the return in the finally -block. The same would apply to any value returned from the catch -block.

Specifications

Specification Status Comment
ECMAScript 3rd Edition (ECMA-262) Standard Initial definition. Implemented in JavaScript 1.4
ECMAScript 5.1 (ECMA-262)
Standard
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of "try statement" in that specification.
Standard
ECMAScript Latest Draft (ECMA-262)
The definition of "try statement" in that specification.
Draft Not part of the current ECMA-262 standard: Multiple catch-blocks and conditional-blocks (SpiderMonkey extension, JavaScript 1.5).

Browser compatibility

The compatibility table on this page is generated from structured data. If you"d like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

Update compatibility data on GitHub

Desktop Mobile Server
Chrome Edge Firefox Internet Explorer Opera Safari Android webview Chrome for Android Firefox for Android Opera for Android Safari on iOS Samsung Internet Node.js
try...catch Chrome Full support 1 Edge Full support 12 Firefox Full support 1 IE Full support 5 Opera Full support Yes Safari Full support Yes WebView Android Full support 1 Chrome Android Full support 18 Firefox Android Full support 4 Opera Android Full support Yes Safari iOS Full support Yes Samsung Internet Android Full support 1.0 nodejs Full support Yes
Conditional clauses

Deprecated Non-standard

Chrome No support No Edge No support No Firefox No support 1 - 59 IE No support No Opera No support No Safari No support No WebView Android No support No Chrome Android No support No Firefox Android No support 4 - 59 Opera Android No support No Safari iOS No support No Samsung Internet Android No support No nodejs No support No
Optional catch binding Chrome Full support 66 Edge No support No Firefox Full support 58 IE No support No Opera Full support 53 Safari Full support 11.1 WebView Android Full support 66 Chrome Android Full support 66 Firefox Android Full support 58 Opera Android Full support 47 Safari iOS Full support 11.3 Samsung Internet Android Full support 9.0 nodejs Full support 10.0.0

Legend

Full support Full support No support No support Non-standard. Expect poor cross-browser support. Non-standard. Expect poor cross-browser support. Deprecated. Not for use in new websites. Deprecated. Not for use in new websites.

Данная статья расчитана для двух типов разработчиков:
- кто еще не знаком с исключениями
- кто пытается найти более разумное использование исключениям

В статье я расскажу о самых основах исключений, о том как можно обходиться без них, а так же о том, как я вижу правильным использование некоторых возможностей языка…

Эволюция языков программирования приводит иногда к кардинальным изменениям в мировоззрении разработчиков. В мире РНР такое случилось при появлении пятой ветки, которая принесла новую объектную модель, новые наборы встроенных функций и новые методы обработки ошибок…

Те, кто начинал знакомиться с PHP (тут и далее я буду подразумевать пятую версию), после другого процедурного языка программирования, так и не поняли что же такого в переходе от 4ки к 5ке и продолжают оформлять код привычными функциями, которые находятся на одном уровне по отношению друг к другу, а так же каждое действие проверяют на удачный код возврата. Но те кто знали об исключениях и классах…

Теория

Исключение (Exception) - сигнал отправляемый программой в интерпретатор, о возникновении нештатной (исключительной) ситуации во время исполнения кода.

В PHP работа с исключениями основана на тех же принципах что и везде. Для генерации исключения используется оператор throw, которому передается объект исключения, принимающий в конструкторе два необязательных параметра: сообщение исключения и код исключения.

throw new Exception(\\\"This is exception message\\\", $exception_code);

Для того, что бы отловить исключение, используется конструкция try...catch. В блоке try выполняются операции, которые могут привести к исключительной ситуации, а блок catch позволяет принять решение что делать, если исключение было брошено.

try {
throw new Exception(\\\"Exception message\\\");
echo \\\"That code will never been executed\\\";
} catch (Exception $e) {
echo $e->getMessage(); //выведет \\\"Exception message\\\"
}

Как видно из примера, при выбрасывании исключения, остальной код в блоке try выполнен не будет, а управление будет передано в оператор catch, в котором мы указываем, как будет называться объект, в который будет передано выброшенное исключение (в нашем случае - $e). Внутри блока оператора catch, на основании данных из исключения мы можем применять какое-либо действие в зависимости от ситуации. Сейчас мы просто вывели сообщение, которое было передано исключением.

Объект Exception (который кстати можно унаследовать) имеет следующий набор финальных (final) методов:

final function getMessage(); // сообщение исключения
final function getCode(); // код исключения
final function getFile(); // файл из которого брошено исключение
final function getLine(); // строка бросания
final function getTrace(); // массив стека вызовов
final function getTraceAsString(); // массив стека вызовов отформатированый в строку

Практика

Когда же удобно использовать исключения? Да всегда, когда функция или метод может прийти к ошибочной ситуации! На примере встроенной функции mysql_connect() и mysql_select_db(), если бы они бросала исключения при ошибке соединения и выборе базы данных соответственно, код выглядел бы так:
try {
mysql_connect($hostname, $username, $password);
mysql_select_db($dbname);
} catch (Exception $e) {
echo $e->getMessage(); //выведет либо сообщение об ошибке подключения, либо об ошибке выбора
}

И в зависимости от результата мы бы:

* удачно присоединились бы к СУБД и выбрали БД (код в сatch блоке не выполнился бы)
* при неудаче соединения с СУБД, вывели бы соответствующую ошибку и прикатили выполнение сеанса
* при ошибке выбора БД, оповестили бы пользователя об этой неприятности

Теперь самое время спросить: \\\«А зачем нам такая сложная штука, если можно использовать оператор if?\\\».

Первый же ответ: \\\«Потому что так код более читабельный, а обработка ошибок выведена в отдельный блок\\\». Если бы мы использовали оператор if, то код выглядел бы следующим образом:

$connId = mysql_connect($hostname, $username, $password);
if (false == $connId) {
echo \\\"Ошибка подключения к СУБД\\\";
}

$flag = mysql_select_db($dbname);
if (false == $flag) {
echo \\\"Невозможно выбрать базу данных.\\\";
}

Согласитесь, что в предыдущем варианте код выглядит более понятным. Но это еще не все. Теперь обработкой этих ошибок заниматься непосредственно разработчику не обязательно - достаточно выбросить исключение, а его обработкой можно заняться на более высоком уровне. Так же исключения можно передавать цепочкой (chain) наверх:

class MyException extends Exception {}

Try {
try {
//...
throw new Exception(\\\"inner\\\");
//...
} catch (Exception $e) {
throw new MyException(\\\"outer\\\");
}
} catch (MyException $e) {
echo $e->getMessage(); //выведет \\\"outer\\\"
}

Производительность

Пытаясь достичь истины, провел несколько экспериментов с различными типами функций.
Первый тип возвращал статус true и проверялся операторами if...else
Второй тип возвращал статус false и проверялся операторами if...else
Третий тип просто выполнял действия и ничего не возвращал. Проверялся блоком try...catch
Четвертый тип всегда бросал исключение и проверялся в try...catch

Результаты:

True: 0.72382092475891
False: 0.85190796852112
No exception: 0.72565317153931
Exception: 14.176206827164

Как и ожидалось - бросание исключений довольно накладная операция, а вот оба варианта удачного выполнения прошли тесты вровень.
Тесты проводились на примитивных функциях сложения, но в 1кк итераций

Выводы

Когда же использовать исключения? Всегда, когда подразумевается ошибка или нестандартное поведение программы, а так же когда принятие решения об обработке результата необходимо переложить на более высокий уровень.
А что же делать с оператором if и булевыми статусами отработки функций? Оставить их. Но толко там где они действительно необходимы. Тоесть там, где логический оператор подразумевает использование результата в вычислениях, а не контроле потока выполнения. Тоесть все удачные завершения функций теперь не нужно оповещать оператором return true, если это логическое значение не пригодиться для дальнейших вычислений. И в то же время все статусы завершения функций с ошибками изменить из формата return false в формат throw new Exception()
Что нужно помнить? Использование исключений предполагает что весь код выполняется со статусом true (без ошибок), но если ошибка произошла, то для ее обработки всегда найдется место в блоке catch.

На этом уроке мы познакомимся с оператором обработки исключений try...catch , который предназначен для перехвата ошибок в некотором блоке кода и их обработки.

Применение оператора try...catch

Оператор обработки исключений try...catch обычно применяется в следующих ситуациях:

  • Для некоторого участка кода, в котором может возникнуть ошибка;
  • Для валидации (проверки) данных перед отправкой на сервер;
  • Для использования в сложных случаях при написании кроссбраузерных приложений.

Теперь давайте рассмотрим, что же произойдет в сценарии на JavaScript при возникновении ошибки и для чего нужен оператор try...catch .

Если в сценарии на языке JavaScript появится ошибка, то дальнейшее выполнение программы будет прекращено. Т.е. инструкции (операторы), которые идут после ошибки выполняться не будут. Но если нам необходимо выполнение программы не прерывать, а переходить к следующей инструкции после той, где может возникнуть ошибка, то эту инструкцию необходимо заключить в оператор " try...catch ".

Синтаксис оператора try...catch

Принцип работы с оператором try...catch заключается в следующем:

Блок, в котором могут возникнуть ошибки, мы обрамляем фигурными скобками, и перед ним пишем ключевое слово try (с англ. попробовать). После этого блока пишем ключевое слово catch (с англ. поймать, ловить) и в круглых скобках указываем переменную, в которой будем хранить информацию об ошибке. Далее фигурными скобками обрамляем блок, предназначенный для обработки ошибок.

Принцип работы оператора try...catch

Оператор обработки исключений работает следующим образом:

Сначала он пытается выполнить все инструкции (операторы), указанные в блоке try . Если внутри блока try ошибки не возникает, то блок catch просто игнорируется, т.е. он не выполняется. В том случае если внутри блока try возникает ошибка, то оставшиеся операторы в этом блоке будут проигнорированы (т.е. они выполняться не будут) и сразу же начнут выполняться операторы внутри блока catch . Самое главное то, что инструкции, идущие после оператора try...catch , продолжат выполняться и работа программы не остановится.

Try { document.write("Первая строка"); documant.write("Вторая строка"); document.write("Третья строка"); } catch (e) { alert("Ошибка:" + e.message); }

В результате выполнения кода в 4 строчке произойдет ошибка, т.к. оператор documant браузером будет не определён. В этом случае 5 строчка браузером выполнена не будет, т.к. начнут выполняться операторы в блоке catch . В качестве параметра блока catch определим переменную e , в которой будет хранить информацию об ошибке. Данную переменную мы будем использовать в операторе alert для вывода сообщения об ошибке.

Блок finally

У оператора обработки исключений есть ещё один блок, который называется finally . Данный блок является не обязательным, и его можно использовать только при необходимости. Он не имеет параметров и в отличие от блока catch выполняется всегда, вне зависимости от того возникла ошибка или нет.

Но так как инструкции, идущие после оператора try...catch тоже выполняются всегда, то возникает вопрос: "Зачем нужен блок finally?"

На самом деле, инструкции, идущие после try...catch , выполняются не всегда. Это может произойти только в том случае, если произойдет ошибка в блоке catch . Когда это произойдёт, программа приостановит своё выполнение и операторы, идущие после конструкции try...catch выполняться не будут. Единственный блок инструкций (операторов), который будет выполняться – это блок finally .

Try { document.write("Первая строка
"); documant.write("Вторая строка
"); document.write("Третья строка
"); } catch (e) { alrt("Ошибка:" + e.message); } finally { document.write("Завершающие действия"); } alert("Операторы после try...catch");

В результате выполнения кода оператор alert , идущий после конструкции try...catch так и не будет выполнен.

Исключительной ситуацией, или исключением (exception), называется прерывание нормального потока выполнения программы в ответ на непредвиденное или аварийное событие, которое порождается ошибками в аппаратуре или в самой программе, например делением на нуль или обращением к памяти по некорректному адресу, а также генерируется программно, например, функциями динамической библиотеки или Win32 при возникновении ситуации, не позволяющей завершить задачу.

Язык C++ предоставляет простой механизм обработки исключений перечисленных типов. Если обработчик для какого-либо исключения не предусмотрен, то стандартный обработчик генерирует сообщение об ошибке и завершает выполнение программы. При обработке исключения можно либо исправить ошибки и продолжить корректную работу программы, или освободить все используемые ресурсы и корректно завершить программу.

Обработка программных исключений. При тестировании и отладке программы программист может объявить любую ее часть контролируемой, например:

  • ввод исходных данных;
  • вычисления по определенным формулам;
  • переход по какой-то ветви по определенному условию;
  • проход определенной итерации цикла;
  • выход из цикла и т. д.

В этом случае он особым образом выделяет эту часть программы и выбирает любую ситуацию, которую ему необходимо проверить при выполнении программы, например выход за границы массива, деление на нуль, достижение какой-то переменной некоторого значения и т. д. Выбранная часть программы называется контролируемой ее частью, а выбранная ситуация - исключением, на которую программа должна прореагировать особым образом - вывести на экран специальное сообщение, прервать свою работу и вызвать обработчик исключения.

Покажем на примере, как обрабатывать исключения, генерируемые программно, с использованием оператора throw, за которым следует некоторое значение. Значение может быть константой, переменной или объектом (т. е. экземпляром класса, структуры или объединения), оно предназначено для передачи информации об исключении, которая может использоваться его обработчиком. В приведенном ниже фрагменте программы при некорректном выделении памяти генерируется исключение со строкой, поясняющей ошибку.

char *Buffer = new char ;

if (Buffer = = 0)

throw "out of memory"; //нехватка памяти

Если исключение сгенерировано, но в программе не предусмотрена его обработка, механизм исключений вызывает из стандартной динамической библиотеки языка C++ функцию завершения terminate, которая выдает сообщение «abnormal program termination», которое не сообщает никаких сведений о причине и месте прерывания программы и прекращает выполнение программы.

Для обработки такого исключения с сообщением причины прерывания и выполнения необходимых только в этом случае действий необходимо предусмотреть операторы tryncatch (задать контролируемую часть программы), как показано в следующем примере.

{ //начало контролируемого блока

//операторы ...

char *Buffer = new char ; if (Buffer = = 0)

throw "out of memory";

//генерация исключения с параметром - строкой

//операторы...

} //конец контролируемого блока

//обработка исключения

catch (char *ErrorMsg) /^определение функции обработки ошибки, параметром которой является любая строка char *ErrorMsg*/

cout « ErrorMsg « " "; /* вывод сообщения об ошибке (обработка

ошибки) и вызов диалогового окна для возобновления выполнения программы или вызов функции exit

} //конец блока обработки исключений контролируемого блока

/*здесь выполнение программы продолжается, если не произошло прерывание

работы программы в контролируемом блоке... */

Если исключение генерируется в любом месте контролируемого блока, следующем за оператором try (или внутри любой функции в этом блоке), то управление передается за пределы блока try. Если за try следует подходящий блок catch, то управление переходит к нему. Блок catch начинается с объявления в круглых скобках. Если тип параметра в этом объявлении совпадает с типом значения в операторе throw, генерирующем исключение, то управление передается данному блоку catch. При несовпадении типов параметров программа ищет другой обработчик catch, тип параметра которого совпадает с типом параметра исключения, и т. д. до конца блока обработки исключений контролируемого блока. После выполнения кода в блоке catch управление передается первому оператору, следующему за блоком обработки исключений, и программа возобновляет работу в нормальном режиме (если блок catch не содержит оператор return или вызов функции exit). Таким образом, операторы try и catch могут предотвратить завершение программы стандартным обработчиком исключений, заменив обработку исключений специальным, понятным программистам способом с указанием места и причины исключения.

Блок try называют охраняемым (контролируемым) разделом кода. Если исключение не сгенерировано, то поток управления «перепрыгнет» все блоки catch и перейдет на первый, следующий за блоком оператор.

В приведенном выше примере оператор throw содержит строку «out of memory». Так как тип параметра в объявлении catch (char *) такой же, то данный блок catch получает управление при вызове этого исключения.

Обратите внимание: оператор catch объявляет параметр типа char * с именем ErrorMsg, что позволяет внутри блока catch получить доступ к значению, заданному в throw. Данный механизм очень

похож на механизм передачи параметров функции. Чтобы понять это, можно представить оператор throw как вызов функции:

throw "out of memory";,

в котором значение («out of memory») передается в функцию.

Также можно представить блок catch как вызываемую функцию, а объявление char * Errormsg как объявление ее формального параметра. Как и параметры функции, переменная ErrorMsg доступна только внутри catch.

Заметьте: в операторе catch может содержаться только описание типа без имени параметра.

//не использует значение, определенное в операторе throw

В этом случае блок catch, как и прежде, получит управление по оператору throw " out of memory", но без доступа к значению типа

Если оператор catch определяет какой-либо другой тип параметра (например, int), блок не получит управление при возникновении данного исключения.

catch (int ErrorCode)

/*управление НЕ будет получено после выполнения оператора throw "out of memory"*/

Если поместить несколько catch за блоком try, то можно управлять различными типами исключений. Например, в следующем фрагменте программы обрабатываются исключения с аргументом типа char * или int.

char *Bufferl = new char ; /*попытка выделить память

под WOO символов и записать указатель на эту область памяти

в Buf f erl*/

if (Bufferl = = 0)

throw "out of memory Bufferl"; /* генерация исключения

с параметром-строкой - это исключение обрабатывается

первым блоком catch V

char *Buffer2 = new char ; /^попытка выделить память

под 1000 символов и записать указатель на эту область памяти в Buf f ег2 */

if (Buffer2 = = 0)

//если память не удалось выделить, генерируем исключение throw "out of memory Buffer2"; /*генерация исключения

с параметром-строкой это исключение обрабатывается

первым блоком catch V

for (i=0; iclOOO; i++) if (Buffer2[i]==0)

throw i; //это исключение обрабатывается вторым блоком catch Bufferl[і]=Bufferl[і]/Buffer2[i];

//обработка исключений

catch (char *ErrorMsg) /*определение функции обработки ошибки, параметром которой является любая строка char *ErrorMsg*/

cout « ErrorMsg « " "; exit для остановки работы программы*/

catch (int ErrorCode) //обработка любого исключения типа int { cout «"Арифметическая ошибка при i - "«ErrorCode«endl;

/*вывод сообщения об ошибке (обработка ошибки) и вызов диалогового окна для возобновления выполнения программы или вызов функции exit для остановки работы программы* /

Если объявление блока catch содержит многоточие, то он получает управление в ответ на исключение любого типа, сгенерированное предыдущими блоками try.

//получает управление в ответ на исключения любого типа

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