Java: Операторы throw и throws. Объявление об исключении throws

В программировании часто возникают ситуации, когда программисту необходимо самому инициировать генерацию исключения для указания, напри­мер, на заведомо ошибочный результат выполнения операции, на некорректные значения параметра метода и др. Исключительную ситуацию можно создать с помощью оператора throw , если объект-исключение уже существует, или инициализировать его прямо после этого оператора. Оператор throw используется для генерации исключения. Для этого может быть использован объект класса Throwable или объект его подкласса, а также ссылки на них. Общая форма записи инструкции throw , генерирующей исключение:

throw объектThrowable;

Объект-исключение может уже существовать или создаваться с помощью оператора new :

t hrow new IOException () ;

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

Ниже приведен пример, в котором сначала создается объект-исключение, затем оператор throw генерирует исключение, обрабатываемое в разделе catch ,
в котором генерируется другое исключение.

/* пример # 3: генерация исключений: ThrowGeneration . java */

package chapt08;

import java.io.File;

public class ThrowGeneration {

public static void connectFile(File file) {

if (file == null || !file.exists())

throw new IllegalArgumentException();/* генерация

исключения */

//

public static void main(String args) {

File f = new File("demo.txt");

// File f = null;

connectFile (f);

} catch (IllegalArgumentException e) {

System.err .print("обработка unchecked-"

+ " исключения вне метода: " + e);

Вызываемый метод connectFile () может (при отсутствии файла на диске или при аргументе null ) генерировать исключение, перехватываемое обработчиком. В результате этого объект непроверяемого исключения IllegalArgument Exception , как подкласса классаRuntime Exception , передается обработчику исключений в методе main() .

В случае генерации проверяемого исключения компилятор требует обра­ботки исключения в методе или отказа от нее с помощью инструкции throw s .

Если метод генерирует исключение с помощью оператора throw и при этом блок catch в методе отсутствует, то для передачи обработки исключения вызывающему методу тип проверяемого (checked) класса исключений должен быть указан в операторе throws при объявлении метода. Для исключений, являющихся подклассами класса RuntimeException (unchecked) и используемых для отображения программных ошибок, при выполнении приложения throws в объявлении должен отсутствовать.

Microsoft Visual C++ и MFC. Программирование для Windows 95 и Windows NT Фролов Александр Вячеславович

Операторы try, throw и catch

Операторы try, throw и catch

Оператор try открывает блок кода, в котором может произойти ошибка. Если ошибка произошла, то оператор throw вызывает исключение. Исключение обрабатывается специальным обработчиком исключений. Обработчик исключения представляет собой блок кода, который начинается оператором catch.

Допустим ваше приложение должно вычислять значение выражения res = 100 / (num * (num – 7)). Если вы зададите значение переменной num, равное 0 или 7, то произойдет ошибка деления на нуль. Участок программы, в котором может случиться ошибка, объединим в блок оператора try. Вставим перед вычислением выражения проверку переменной nem на равенство нулю и семи. Если переменная num примет запрещенные значения, вызовем исключение, воспользовавшись оператором throw.

Сразу после блока try поместите обработчик исключения catch. Он будет вызываться в случае ошибки.

Пример такой программы, получившей название Exception, мы привели в листинге 1.1. Программа Exception принимает от пользователя значение переменной num, а затем вычисляет выражение res = 100 / (num * (num – 7)) и отображает полученный результат на экране.

В случае, если пользователь введет число 0 или 7, тогда вызывается исключение throw. В качестве параметра оператору throw указывается переменная num. Заметим, что так как переменная num имеет тип long, считается что данное исключение также будет иметь тип long.

После вызова оператора throw управление сразу передается обработчику исключения соответствующего типа. Определенный нами обработчик отображает на экране строку "Exception, num = ", а затем выводит значение переменной num.

После обработки исключения, управление не возвращается в блок try, а передается оператору, следующему после блока catch данного обработчика исключения. Программа выведет на экран строку “Stop program” и завершит свою работу.

Если пользователь введет разрешенные значения для переменной num, тогда исключение не вызывается. Программа вычислит значение res и отобразит его на экране. В этом случае обработчик исключения не выполнится и управление перейдет на оператор, следующий за блоком обработки исключения. Программа выведет на экран строку “Stop program” и завершит работу.

Листинг 1.1. Файл Exception.cpp

#include

// Введите число num

cout << "Input number: ";

cin >> num;

// Блок try, из которого можно вызвать исключение

if ((num == 7) || (num == 0))

// Если переменная num содержит значение 0 или 7,

// тогда вызываем исключение типа float

// Значения num равные 0 или 7 вызовут ошибку

// деления на нуль в следующем выражении

res = 100 / (num * (num – 7));

// Отображаем на экране результат вычисления

cout << "Result = " << res << endl;

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

catch(long num) {

cout << "Exception, num = " << num << endl;

cout << "Stop program" << endl;

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

// Отображаем на экране значение переменной num

cout << "Exception, num = " << num << endl;

Из книги Linux для пользователя автора Костромин Виктор Алексеевич

5.3.3 Операторы && и || Операторы и || являются управляющими операторами. Если в командной строке стоит command1 command2, то command2 выполняется в том, и только в том случае, если статус выхода из команды command1 равен нулю, что говорит об успешном ее завершении. Аналогично, если

Из книги Справочное руководство по C++ автора Страустрап Бьярн

5.5.1 Операторы ›, ‹ и ›› Для обозначения перенаправления используются символы "›", "‹" и "››". Чаще всего используется перенаправление вывода команды в файл. Вот соответствующий пример:$ ls -l › /home/jim/dir.txtПо этой команде в файле /home/jim/dir.txt будет сохранен перечень файлов и

Из книги Язык программирования С# 2005 и платформа.NET 2.0. автора Троелсен Эндрю

R.17.6 Операторы оператор: помеченный-оператор оператор-выражение составной-оператор выбирающий-оператор оператор-цикла оператор-перехода оператор-описанияпомеченный-оператор: идентификатор: оператор case выражение-константа: оператор default:

Из книги Delphi. Учимся на примерах автора Парижский Сергей Михайлович

Общие операторы catch В C# также поддерживается "общий" блок catch, который не получает явно объект исключения, генерируемый данным членом.// Блок catch общего вида.static void Main(string args) { … try { for (int i = 0; i ‹ 10; i++) myCar.Accelerate(10); } catch { Console.WriteLine("Случилось что-то ужасное…"); } … }Очевидно,

Из книги Windows Script Host для Windows 2000/XP автора Попов Андрей Владимирович

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

Из книги HTML 5, CSS 3 и Web 2.0. Разработка современных Web-сайтов. автора Дронов Владимир

Операторы отношения и логические операторы Операторы отношения используются для сравнения значений двух переменных. Эти операторы, описанные в табл. П2.11, могут возвращать только логические значения true или false.Таблица П2.11. Операторы отношения Оператор Условие, при

Из книги Язык программирования Си для персонального компьютера автора Бочков C. О.

Операторы Операторов язык JavaScript поддерживает очень много - на все случаи жизни. Их можно разделить на несколько групп. Арифметические операторы Арифметические операторы служат для выполнения арифметических действий над числами. Все арифметические операторы,

Из книги Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ автора Борри Хелен

ОПЕРАТОРЫ Введение Операторы языка Си управляют процессом выполнения программы. Набор операторов языка Си содержит все управляющие конструкции структурного программирования. Ниже представлен полный список операторов:пустой операторсоставной оператор или

Из книги Искусство программирования на языке сценариев командной оболочки автора Купер Мендель

Операторы SQL Оператор SQL используется для выполнения запроса к базе данных. Язык запросов выражается в операторах, которые задают цель: что должно быть сделано (операция), объекты, с которыми это должно быть сделано, и детализация, как это должно быть сделано. По теории

Из книги Язык Си - руководство для начинающих автора Прата Стивен

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

Из книги СПРАВОЧНИК ПО WinAPI автора

8.1. Операторы присваиваниеvariable assignmentИнициализация переменной или изменение ее значения=Универсальный оператор присваивания, пригоден как для сравнения целых чисел, так и для сравнения строк.var=27category=minerals # Пробелы до и после оператора "=" -- недопустимы. Пусть вас не

Из книги Linux и UNIX: программирование в shell. Руководство разработчика. автора Тейнсли Дэвид

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

Из книги Основы программирования на Java автора Сухов С. А.

Catch Описание: function Catch(var CatchBuf): Integer;Копиpует состояние всех pегистpов системы и указатель команды в CatchBuf.Паpаметpы:CatchBuf: TCatchBuf для копиpования сpеды выполнения.Возвpащаемое значение:Нуль, если сpеда скопиpована.См. также:

Из книги автора

Throw Описание: function Throw(var CatchBuf: TCatchBuf; ThrowBack:: Integer);Восстанавливает сpеду выполнения пpикладной задачи. Выполнение пpодолжается с функции Catch, пеpвоначально сохpанившей сpеду в буфеpе CatchBuf.Паpаметpы:CatchBuf: TCatchBuf, содеpжащая сpеду выполнения.ThrowBack: Значение, возвpащаемое функции

Из книги автора

Из книги автора

4. ОПЕРАТОРЫ Операторы в языке Java - это специальные символы, которые сообщают транслятору о том, что вы хотите выполнить операцию с некоторыми операндами. Типы операций указываются с помощью операторов, а операнды - это переменные, выражения или литералы. Некоторые

Введение

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

Темные дни С

Типичная функция, написанная на С, выглядит примерно так:

Long DoSomething() { long *a, c; FILE *b; a = malloc(sizeof(long) * 10); if (a == NULL) return 1; b = fopen("something.bah", "rb"); if (b == NULL) { free(a); return 2; } fread(a, sizeof(long), 10, b); if (a != 0x10) { free(a); fclose(b); return 3; } fclose(b); c = a; free(a); return c; }

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

Try-catch-throw

Давайте же разберем основы обработки исключений в С++. Чтобы комфортно работать с исключениями в С++ вам нужно знать лишь три ключевых слова:

  • try (пытаться) - начало блока исключений;
  • catch (поймать) - начало блока, "ловящего" исключение;
  • throw (бросить) - ключевое слово, "создающее" ("возбуждающее") исключение.

А теперь пример, демонстрирующий, как применить то, что вы узнали:

Void func() { try { throw 1; } catch(int a) { cout << "Caught exception number: " << a << endl; return; } cout << "No exception detected!" << endl; return; }

Если выполнить этот фрагмент кода, то мы получим следующий результат:

Caught exception number: 1

Теперь закоментируйте строку throw 1; и функция выдаст такой результат:

No exception detected!

Как видите все очень просто, но если это применить с умом, такой подход покажется вам очень мощным средством обработки ошибок. Catch может "ловить" любой тип данных, так же как и throw может "кинуть" данные любого типа. Т.е. throw AnyClass(); будет правильно работать, так же как и catch (AnyClass &d) {};.

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

Catch(dumbclass) { }

так же, как и

Catch(dumbclass&) { }

Так же можно "поймать" и все исключения:

Catch(...) { }

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

Try { throw 1; // throw "a"; } catch (long b) { cout << "пойман тип long: " << b << endl; } catch (char b) { cout << "пойман тип char: " << b << endl; }"

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

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

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

Перегрузка глобальных операторов new/delete

А сейчас хотелось бы отправить вас к статье "Как обнаружить утечку памяти". В ней рассказывается, как обнаружить неправильное управление распределением памяти в вашей программе. Вы можете спросить, при чем тут перегрузка операторов? Если перегрузить стандартные new и delete, то открываются широкие возможности по отслеживанию ошибок (причем ошибок часто критических) с помощью исключений. Например:

Char *a; try { a = new char; } catch (...){ // a не создан - обработать ошибку распределения памяти, // выйти из программы и т.п. } // a успешно создан, продолжаем выполнение

Это, на первый взгляд, кажется длиннее, чем стандартная проверка в С "а равен NULL?", однако если в программе выделяется десяток динамических переменных, то такой метод оправдывает себя.

Операторы throw без параметров

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

Try { throw; // ни один оператор, следующий далее (до закрывающей скобки) // выполнен не будет } catch(...) { cout << "Исключение!" << endl; }

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

Приложение

Приведем пример, как все вышеизложенное может быть использовано в конкретном приложении. Преположим, у вас в программе есть класс cMain и экземпляр этого класса Main: class cMain { public: bool Setup(); bool Loop(); // Основной цикл программы void Close(); }; cMain Main;

А в функции main() или WinMain() вы можете использовать этот класс как-нибудь так:

Try { Main.Setup(); Main.Loop(); Main.Close(); } catch (Exception &e) { // использование класса, ведущего лог. log("Exception thrown: %s", e.String()); // Показываем сообщение об ошибке и закрываем приложение. }

Основной цикл программы может выглядеть примерно так:

While (AppActive) { try { // какие-то действия } catch (Exception &e) { /* Если исключение критическое, типа ошибки памяти, посылаем исключение дальше, в main(), оператором throw e; или просто throw. Если исключение некритично, обрабатываем его и возвращаемся в основной цикл. */ } }

Заключение

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

Операторы throw и finally

Оператор throw

Исключение может быть сгенерировано вручную с помощью оператора throw . Ниже приведена общая форма такого генерирования:

throw exceptOb;

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

Using System; namespace ConsoleApplication1 { class Program { static void Main() { int i = int.Parse(Console.ReadLine()); byte j; try { if (i > 255) // Генерируем исключение throw new OverflowException(); else j = (byte)i; } catch (OverflowException) { Console.WriteLine("Возникло переполнение"); } Console.ReadLine(); } } }

Обратите внимание на то, что исключение OverflowException было сгенерировано с использованием ключевого слова new в операторе throw. Не следует забывать, что в данном случае генерируется конкретный объект, а следовательно, он должен быть создан перед генерированием исключения. Это означает, что сгенерировать исключение только по его типу нельзя. В данном примере для создания объекта OverflowException был автоматически вызван конструктор, используемый по умолчанию, хотя для генерирования исключений доступны и другие конструкторы.

Повторное генерирование исключений

Исключение, перехваченное в одном блоке catch, может быть повторно сгенерировано в другом блоке, чтобы быть перехваченным во внешнем блоке catch. Наиболее вероятной причиной для повторного генерирования исключения служит предоставление доступа к исключению нескольким обработчикам. Допустим, что один обработчик оперирует каким-нибудь одним аспектом исключения, а другой обработчик - другим его аспектом. Для повторного генерирования исключения достаточно указать оператор throw без сопутствующего выражения, как в приведенной ниже форме:

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

Using System; namespace ConsoleApplication1 { class Program { static void Del(int x, int y) { try { int result = x / y; } catch(DivideByZeroException) { Console.WriteLine("Деление на ноль!"); throw; } } static void Main() { try { Del(5, 0); } catch (DivideByZeroException) { Console.WriteLine("Программная ошибка!"); } Console.ReadLine(); } } }

Как видите, исключение DivideByZeroException обрабатывается как во внутреннем блоке, так и во внешнем.

Использование блока finally

Иногда требуется определить кодовый блок, который будет выполняться после выхода из блока try/catch. В частности, исключительная ситуация может возникнуть в связи с ошибкой, приводящей к преждевременному возврату из текущего метода. Но в этом методе мог быть открыт файл, который нужно закрыть, или же установлено сетевое соединение, требующее разрывания. Подобные ситуации нередки в программировании, и поэтому для их разрешения в C# предусмотрен удобный способ: воспользоваться блоком finally .

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

Для того чтобы указать кодовый блок, который должен выполняться после блока try/catch, достаточно вставить блок finally в конце последовательности операторов try/catch. Ниже приведена общая форма совместного использования блоков try/catch и finally:

try { // Блок кода, предназначенный для обработки ошибок. } catch (ExcepTypel exOb) { // Обработчик исключения типа ExcepTypel } catch (ExcepType2 exOb) { // Обработчик исключения типа ЕхсерType2. } finally { // Код завершения обработки исключений. }

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