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

Содержание:

Обработка исключений[править]

Чтобы сгенерировать исключение используется ключевое слово . Как и любой объект в Java, исключения создаются с помощью .

 (t == ) {
     NullPointerException();
}

Есть два стандартных конструктора для всех исключений: первый — конструктор по умолчанию, второй принимает строковый аргумент, поэтому можно поместить подходящую информацию в исключение.

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

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

 f()  InterruptedException, IOException { 

try-catch-finallyправить

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

 {
    
}

Сразу после блока проверки следуют обработчики исключений, которые объявляются ключевым словом catch.

 {
    
} (Type1 id1) {
    
} (Type2 id2) {
    
}

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

Код из блока выполнится в любом случае: при нормальном выходе из , после обработки исключения или при выходе по команде .

NB: Если JVM выйдет во время выполнения кода из или , то -блок может не выполниться. Также, например, если поток выполняющий или код остановлен, то блок может не выполниться, даже если приложение продолжает работать.

Блок удобен для закрытия файлов и освобождения любых других ресурсов. Код в блоке должен быть максимально простым. Если внутри блока будет брошено какое-либо исключение или просто встретится оператор , брошенное в блоке исключение (если таковое было брошено) будет забыто.

 java.io.IOException;

 ExceptionTest {
   
     main(String[] args) {
         {
             {
                Exception();
            }  {
                 IOException();
            }
        }  (IOException ex) {
            System..println(ex.getMessage());
        }  (Exception ex) {
            System..println(ex.getMessage());
        }
    }
}

После того, как было брошено первое исключение — — будет выполнен блок , в котором будет брошено исключение , именно оно будет поймано и обработано. Результатом его выполнения будет вывод в консоль . Исходное исключение теряется.

Обработка исключений, вызвавших завершение потокаправить

При использовании нескольких потоков бывают ситуации, когда поток завершается из-за исключения. Для того, чтобы определить с каким именно, начиная с версии Java 5 существует интерфейс . Его реализацию можно установить нужному потоку с помощью метода . Можно также установить обработчик по умолчанию с помощью статического метода .

Интерфейс имеет единственный метод , в который передается экземпляр потока, завершившегося исключением, и экземпляр самого исключения. Когда поток завершается из-за непойманного исключения, JVM запрашивает у потока , используя метод , и вызвает метод обработчика – . Все исключения, брошенные этим методом, игнорируются JVM.

Информация об исключенияхправить

  • . Этот метод возвращает строку, которая была первым параметром при создании исключения;
  • возвращает исключение, которое стало причиной текущего исключения;
  • печатает stack trace, который содержит информацию, с помощью которой можно определить причину исключения и место, где оно было брошено.
Exception in thread "main" java.lang.IllegalStateException: A book has a null property
        at com.example.myproject.Author.getBookIds(Author.java:38)
        at com.example.myproject.Bootstrap.main(Bootstrap.java:14)
Caused by: java.lang.NullPointerException
        at com.example.myproject.Book.getId(Book.java:22)
        at com.example.myproject.Author.getBookIds(Author.java:35)

Все методы выводятся в обратном порядке вызовов. В примере исключение было брошено в методе , который был вызван в . «Caused by» означает, что исключение является причиной .

Гарантии безопасности[править]

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

  • Отсутствие гарантий (no exceptional safety). Если было брошено исключение, то не гарантируется, что все ресурсы будут корректно закрыты и что объекты, методы которых бросили исключения, могут в дальнейшем использоваться. Пользователю придется пересоздавать все необходимые объекты и он не может быть уверен в том, что может переиспозовать те же самые ресурсы.
  • Отсутствие утечек (no-leak guarantee). Объект, даже если какой-нибудь его метод бросает исключение, освобождает все ресурсы или предоставляет способ сделать это.
  • Слабые гарантии (weak exceptional safety). Если объект бросил исключение, то он находится в корректном состоянии, и все инварианты сохранены. Рассмотрим пример:
 Interval {
    
    
    double left;
    double right;
    
}

Если будет брошено исключение в этом классе, то тогда гарантируется, что ивариант «левая граница интервала меньше правой» сохранится, но значения и могли измениться.

Сильные гарантии (strong exceptional safety). Если при выполнении операции возникает исключение, то это не должно оказать какого-либо влияния на состояние приложения. Состояние объектов должно быть таким же как и до вызовов методов.

Гарантия отсутствия исключений (no throw guarantee). Ни при каких обстоятельствах метод не должен генерировать исключения. В Java это невозможно, например, из-за того, что VirtualMachineError может произойти в любом месте, и это никак не зависит от кода. Кроме того, эту гарантию практически невозможно обеспечить в общем случае.

Обеспечение доступности данных об исключении при удаленном выполнении кода

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

Например, для реализаций .NET, которые поддерживают домены приложений, могут возникать исключения для этих доменов. Предположим, что домен приложения А создает домен приложения В, который выполняет код, вызывающий исключение. Чтобы домен приложения A правильно перехватил и обработал исключение, он должен найти сборку, которая содержит исключение, порожденное доменом приложения B. Если домен приложения B порождает исключение, содержащееся в сборке в его базовой папке приложения, но не в базовой папке приложения домена A, то домен приложения A не сможет найти исключение и среда CLR породит исключение FileNotFoundException. Чтобы избежать такой ситуации, можно развернуть сборку, содержащую сведения об исключении, двумя способами:

  • Поместите эту сборку в общую базу приложения, совместно используемую обоими доменами приложений.

    — или —

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

Использование блоков try/catch/finally для восстановления после ошибок или высвобождения ресурсов

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

Очистите ресурсы, выделенные с помощью инструкций или блоков . Рекомендуется использовать инструкции для автоматической очистки ресурсов при возникновении исключений. Используйте блоки , чтобы очистить ресурсы, которые не реализуют IDisposable. Код в предложении выполняется почти всегда — даже при возникновении исключений.

std::invalid_argument

Исключение определено в заголовочном файле <stdexcept>

Наследован от std::logic_error. Определяет исключение, которое должно быть брошено в случае неправильного аргумента.

Например, на MSDN приведён пример, когда в объект класса bitset из стандартной библиотеки

// invalid_arg.cpp  
// compile with: /EHsc /GR  
#include <bitset>  
#include <iostream>  
  
using namespace std;  
  
int main( )  
{  
   try   
   {  
      bitset< 32 > bitset( string( "11001010101100001b100101010110000") );  
   }  
   catch ( exception &e )   
   {  
      cerr << "Caught " << e.what( ) << endl;  
      cerr << "Type " << typeid( e ).name( ) << endl;  
   };  
}  
\* Output:   
Caught invalid bitset<N> char  
Type class std::invalid_argument  
*\ 

В данном примере передаётся неправильная строка, внутри которой имеется символ ‘b’, который будет ошибочным.

Ловим исключения

Исключения можно «ловить». Это полезно в нескольких случаях. Иногда мы можем как-то отреагировать на неудачу: например, при ошибке скачивании файла по сети можно сделать паузу и повторить попытку. Для этого нам надо перехватить выброшенное функцией исключение.

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

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

set_exception_handler(function (Exception $exception) {
    // Функция будет вызвана при возникновении исключения        
});

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

Структурная обработка исключений — это когда мы ловим только исключения определенных типов в опредленном месте кода. Она реализуется с помощью /:

try {
    // В try пишется код, в котором мы хотим перехватывать исключения
    $users = loadUsersFromFile(...);
    ....
} catch (LoadUsersException $e) {
    // В catch мы указываем, исключения каких классов хотим ловить.
    // В данном случае мы ловим исключения класса LoadUsersException и его 
    // наследников, то есть только те, которые выбрасывает наша функция
    // Блоков catch может быть несколько, для разных классов

    die("Ошибочка: {$e->getMessage()}\n");
}

В PHP5.5 и выше добавлен блок . Команды из этого блока будут выполнены после любого из блоков ( или ) — в случае если исключения не произойдет и в случае если оно произойдет.

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

class LoadUsersException extends Exception { }

Выкидывать его в

throw new LoadUsersException("Файл $file не существует");

И ловить в только наши исключения:

catch (LoadUsersException $e) {
    .... обрабатываем ошибку ...
}

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

Что называют исключением. Исключения в мире программирования

В программировании исключением называют возникновение ошибки (ошибок) и различных непредвиденных ситуаций в процессе выполнения программы. Исключения могут появляться как в итоге неправильных действий юзера, так и из-за потери сетевого соединения с сервером, отсутствии нужного ресурса на диске и т. п. Также среди причин исключений — ошибки программирования либо неверное использование API.

При этом в отличие от «человеческого мира», программное приложение должно чётко понимать, как поступать в подобной ситуации. И вот как раз для этого в Java и существует механизм исключений (exception).

Создание классов исключений

Последнее обновление: 23.10.2018

Если нас не устраивают встроенные типы исключений, то мы можем создать свои типы. Базовым классом
для всех исключений является класс Exception, соответственно для создания своих типов мы можем унаследовать данный класс.

Допустим, у нас в программе будет ограничение по возрасту:

class Program
{
	static void Main(string[] args)
	{
		try
		{
			Person p = new Person { Name = "Tom", Age = 17 };
		}
		catch (Exception ex)
		{
			Console.WriteLine($"Ошибка: {ex.Message}");
		}
		Console.Read();
	}
}
class Person
{
	private int age;
	public string Name { get; set; }
	public int Age
	{
		get { return age; }
		set
		{
			if (value < 18)
			{
				throw new Exception("Лицам до 18 регистрация запрещена");
			}
			else
			{
				age = value;
			}
		}
	}
}

В классе Person при установке возраста происходит проверка, и если возраст меньше 18, то выбрасывается исключение. Класс Exception принимает
в конструкторе в качестве параметра строку, которое затем передается в его свойство Message.

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

class PersonException : Exception
{
    public PersonException(string message)
        : base(message)
    { }
}

По сути класс кроме пустого конструктора ничего не имеет, и то в конструкторе мы просто обращаемся к конструктору базового класса
Exception, передавая в него строку message. Но теперь мы можем изменить класс Person, чтобы он выбрасывал исключение именно этого типа и
соответственно в основной программе обрабатывать это исключение:

class Program
{
	static void Main(string[] args)
	{
		try
		{
			Person p = new Person { Name = "Tom", Age = 17 };
		}
		catch (PersonException ex)
		{
			Console.WriteLine("Ошибка: " + ex.Message);
		}
		Console.Read();
	}
}
class Person
{
	private int age;
	public int Age
	{
		get { return age; }
		set
		{
			if (value < 18)
				throw new PersonException("Лицам до 18 регистрация запрещена");
            else
				age = value;
		}
	}
}

Однако необязательно наследовать свой класс исключений именно от типа Exception, можно взять какой-нибудь другой
производный тип. Например, в данном случае мы можем взять тип ArgumentException, который представляет исключение,
генерируемое в результате передачи аргументу метода некорректного значения:

class PersonException : ArgumentException
{
	public PersonException(string message)
		: base(message)
	{ }
}

Каждый тип исключений может определять какие-то свои свойства. Например, в данном случае мы можем определить в классе свойство для хранения устанавливаемого значения:

class PersonException : ArgumentException
{
	public int Value { get;}
	public PersonException(string message, int val)
		: base(message)
	{
		Value = val;
	}
}

В конструкторе класса мы устанавливаем это свойство и при обработке исключения мы его можем получить:

class Person
{
	public string Name { get; set; }
	private int age;
	public int Age
	{
		get { return age; }
		set
		{
			if (value < 18)
				throw new PersonException("Лицам до 18 регистрация запрещена", value);
			else
				age = value;
		}
	}
}
class Program
{
	static void Main(string[] args)
	{
		try
		{
			Person p = new Person { Name = "Tom", Age = 13 };
		}
		catch (PersonException ex)
		{
			Console.WriteLine($"Ошибка: {ex.Message}");
			Console.WriteLine($"Некорректное значение: {ex.Value}");
		}
		Console.Read();
	}
}

НазадВперед

Восстановление состояния, если методы не выполняются из-за исключения

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

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

Один из способов обработки в этой ситуации заключается в перехвате всех исключений, выданных транзакцией начисления средств, и откате транзакции списания средств.

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

Классификация исключений[править]

Класс Java описывает все, что может быть брошено как исключение. Наследеники — и — основные типы исключений. Также , унаследованный от , является существенным классом.


Иерархия стандартных исключений

Проверяемые исключенияправить

Наследники класса (кроме наслеников ) являются проверяемыми исключениями(checked exception). Как правило, это ошибки, возникшие по вине внешних обстоятельств или пользователя приложения – неправильно указали имя файла, например. Эти исключения должны обрабатываться в ходе работы программы, поэтому компилятор проверяет наличие обработчика или явного описания тех типов исключений, которые могут быть сгенерированы некоторым методом.

Все исключения, кроме классов и и их наследников, являются проверяемыми.

Errorправить

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

RuntimeExceptionправить

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

Проброс исключения

В примере выше мы использовали для обработки некорректных данных. А что, если в блоке возникнет другая неожиданная ошибка? Например, программная (неопределённая переменная) или какая-то ещё, а не ошибка, связанная с некорректными данными.

Пример:

Конечно, возможно все! Программисты совершают ошибки. Даже в утилитах с открытым исходным кодом, используемых миллионами людей на протяжении десятилетий – вдруг может быть обнаружена ошибка, которая приводит к ужасным взломам.

В нашем случае предназначен для выявления ошибок, связанных с некорректными данными. Но по своей природе получает все свои ошибки из . Здесь он получает неожиданную ошибку, но всё также показывает то же самое сообщение . Это неправильно и затрудняет отладку кода.

К счастью, мы можем выяснить, какую ошибку мы получили, например, по её свойству :

Есть простое правило:

Блок должен обрабатывать только те ошибки, которые ему известны, и «пробрасывать» все остальные.

Техника «проброс исключения» выглядит так:

  1. Блок получает все ошибки.
  2. В блоке мы анализируем объект ошибки .
  3. Если мы не знаем как её обработать, тогда делаем .

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

Ошибка в строке из блока «выпадает наружу» и может быть поймана другой внешней конструкцией (если есть), или «убьёт» скрипт.

Таким образом, блок фактически обрабатывает только те ошибки, с которыми он знает, как справляться, и пропускает остальные.

Пример ниже демонстрирует, как такие ошибки могут быть пойманы с помощью ещё одного уровня :

Здесь знает только, как обработать , тогда как внешний блок знает, как обработать всё.

Учебный пример, в котором есть примеры использования всех классов исключений:

class Example
{
  protected $author;  
  protected $month;  
  protected $goals = [];
  
  public function exceptions(int $a, int $b): int
  {
    $valid_a = ;
    if (!is_int($a)) {
      throw new InvalidArgumentException("a должно быть целочисленным!");
    }
    if ($a > 5 || !in_array($a, $valid_a, true)) {
      throw new DomainException("a не может быть больше 5");
    }
    
    $c = $this->getByIndex($a);
    if (!is_int($c)) {
      throw new RangeException("c посчитался неправильно!");
    } else {
      return $c;
    }      
  }
  
  private function getByIndex($a)
  {
    return ($a < 100) ? $a + 1 : null;
  }
  
  public function deleteNextGoal()
  {
    if (empty($this->goals)) {
      throw new UnderflowException("Нет цели, чтобы удалить!");
    } elseif (count($this->goals) > 100000) {
      throw new OverflowException("Система не может оперировать больше, чем 100000 целями одновременно!");
    } else {
      array_pop($this->goals);
    }
  }
  
  public function getGoalByIndex($i)
  {
    if (!isset ($this->goals)) {
      throw new OutOfBoundsException("Нет цели с индексом $i"); // легитимные значения известны только во время выполнения
    } else {
      return $this->goals;
    }
  }
  
  public function setPublicationMonth(int $month)
  {
    if ($month < 1 || $month > 12) {
      throw new OutOfRangeException("Месяц должен быть от 1 до 12!"); // легитимные значения известны заранее
    }
    $this->month = $month;
  }
  
  public function setAuthor($author)
  {
    if (mb_convert_case($author, MB_CASE_UPPER) !== $author) {
      throw new InvalidArgumentException("Все буквы имени автора должны быть заглавными");
    } else {
      if (mb_strlen($author) > 255) {
        throw new LengthException("Поле автор не должно быть больше 255 сиволов!");
      } else {
        $this->author = $author;
      }
    }
  }
  
  public function __call(string $name, array $args)
  {
    throw new BadMethodCallException("Метод Example>$name() не существует");
  }
}

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

Зачем нам механизм исключений?

Для понимания опять приведём пример из обычного мира. Представьте, что на какой-нибудь автодороге имеется участок с аварийным мостом, на котором ограничена грузоподъёмность. И если по такому мосту проедет грузовик со слишком большой массой, мост разрушится, а в момент этого ЧП ситуация для шофёра станет, мягко говоря, исключительной. И вот, дабы такого не произошло, дорожные службы заранее устанавливают на дороге соответствующие предупреждающие знаки. И тогда водитель, посмотрев на знак, сравнит массу своего авто со значением разрешённой грузоподъёмности и примет соответствующее решение, например, поедет по другой дороге.

То есть мы видим, что из-за правильных действий дорожной службы шоферы крупногабаритных транспортных средств:
1) получили возможность заранее изменить свой путь;
2) были предупреждены об опасности;
3) были предупреждены о невозможности проезжать по мосту при определённых условиях.

Вот как наш жизненный пример соотносится с применением исключения на Java:

Исходя из вышесказанного, мы можем назвать одну из причин применения исключений в Java. Заключается она в возможности предупреждения исключительной ситуации для её последующего разрешения и продолжения работы программы. То есть механизм исключений позволит защитить написанный код от неверного применения пользователем путём валидации входящих данных.

Что же, давайте ещё раз побудем дорожной службой. Чтобы установить знак, мы ведь должны знать места, где водителей ТС могут ждать различные неприятности. Это первое. Далее, нам ведь надо заготовить и установить знаки. Это второе. И, наконец, надо предусмотреть маршруты объезда, позволяющие избежать опасности.

В общем, механизм исключений в Java работает схожим образом. На стадии разработки программы мы выполняем «ограждение» опасных участков кода в отношении наших исключений, используя блок try{}. Чтобы предусмотреть запасные пути, применяем блок catch{}. Код, выполняемый в программе при любом исходе, пишем в блоке finally{}.

Иногда бывает, что мы не можем предусмотреть «запасной аэродром» либо специально желаем предоставить право его выбора юзеру. Но всё равно мы должны как минимум предупредить пользователя об опасности. Иначе он превратится в разъярённого шофёра, который ехал долго, не встретил ни одного предупреждающего знака и в итоге добрался до аварийного моста, проехать по которому не представляется возможным.

Что касается программирования на Java, то мы, когда пишем свои классы и методы, далеко не всегда можем предвидеть контекст их применения другими программистами в своих программах, а значит, не можем со стопроцентной вероятностью предвидеть правильный путь для разрешения исключительных ситуаций. Но предупредить коллег о возможной исключительной ситуации мы всё-таки должны, и это не что иное, как правило хорошего тона.

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

Генерация собственных ошибок

Что если синтаксически корректен, но не содержит необходимого свойства ?

Например, так:

Здесь выполнится без ошибок, но на самом деле отсутствие свойства для нас ошибка.

Для того, чтобы унифицировать обработку ошибок, мы воспользуемся оператором .

Оператор генерирует ошибку.

Синтаксис:

Технически в качестве объекта ошибки можно передать что угодно. Это может быть даже примитив, число или строка, но всё же лучше, чтобы это был объект, желательно со свойствами и (для совместимости со встроенными ошибками).

В JavaScript есть множество встроенных конструкторов для стандартных ошибок: , , , и другие. Можно использовать и их для создания объектов ошибки.

Их синтаксис:

Для встроенных ошибок (не для любых объектов, только для ошибок), свойство – это в точности имя конструктора. А свойство берётся из аргумента.

Например:

Давайте посмотрим, какую ошибку генерирует :

Как мы видим, это .

В нашем случае отсутствие свойства – это ошибка, ведь пользователи должны иметь имена.

Сгенерируем её:

В строке оператор генерирует ошибку с сообщением . Точно такого же вида, как генерирует сам JavaScript. Выполнение блока немедленно останавливается, и поток управления прыгает в .

Теперь блок становится единственным местом для обработки всех ошибок: и для и для других случаев.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *