Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Part6(9-прилож)+++а.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
1.82 Mб
Скачать

9.10. Исключения

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

Так что же такое исключение?

Исключение (exception) – это объект, выдаваемой системой выполнения программы (CLR для C# или JVM для Java), когда при исполнении программы случилась неопределённая ситуация, система не знает что делать и выбрасывает (throw) специальный объект (exception), содержащий информацию о случившемся. Если программист предусмотрел возможность появления этого объекта, схватил (catch) его и среагировал надлежащим образом, то аварийное завершение не случится – программа продолжит нормально функционировать. Иначе, к глубокому сожалению, выполнение программы завершится аварийно.

Пример 9.10.1 иллюстрирует аварийное завершение программы при делении на нуль.

Пример 9.10.1. Исключение не обрабатывается.

///////////////

// Java или J#

package cjLecExc_1;

public class Exc

{

public static void main ( )

{

int x, y, z;

x= 5; y= 0; z= x/y;

System.out.println ("z= "+z);

}

}

/*

Result:

На консоль выдаётся информация об аварийном завершении программы:

Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.

at cjLecExc_1.Exc.main( ) in c:\VS_Programs\cjLecExc_1\Class1.jsl

:line 9

Press any key to continue

*/

///////////////

// C#

using System;

class Exc

{

static void Main ( )

{

int x, y, z;

x= 5; y= 0; z= x/y;

Console.WriteLine ("z= "+z);

}

}

/*

Result:

На консоль выдаётся информация об аварийном завершении программы:

Unhandled Exception: System.DivideByZeroException: Attempted to divide by zero.

at Class1.Main( ) in c:\vs_programs\cslecexc_1\class1.cs:line 8

Press any key to continue

*/

До выброса исключения функция Main() и main() присвоили значения переменным x и y. При делении x на нулевое значение переменной y выброшено исключение, работа программы прерывается, и, заметьте, функции WriteLine() и println() не выполняются: на консоль не выдаётся значение переменной z. Как видно из результата работы программы, на консоль выдана информация о необработанном программистом исключении (unhandled exception) типа DivideByZeroException (попытка разделить на нуль).

Для обработки исключения применяется try-catch-finally конструкция:

try

{

контролируемый программный код

}

catch (тип-исключения объект-исключения )

{

обработчик исключения для объекта типа

}

[ finally

{

обработка перед выходом из try-блока

}]

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

finally-блок может отсутствовать. Последовательность его операторов выполняется перед возвратом из try-блока.

Пример 9.10.2 иллюстрирует обработку DivideByZeroException исключения.

Пример 9.10.2. Обрабатка DivideByZeroException исключения.

///////////////

// Java или J#

package cjLecExc_2b;

public class Exc

{

public static void main(String[] args)

{

int x, y, z;

try

{

x= 5; y= 0; z= x/y;

System.out.println("z= "+z);

}

catch(ArithmeticException e)

{System.out.println(“Exception is catched”);}

}

}

/*

Result:

Exception is catched

Press any key to continue

*/

///////////////

// C#

using System;

class Exc

{

static void Main(string[] args)

{

int x, y, z;

try

{

x= 5; y= 0; z= x/y;

Console.WriteLine("z= "+z);

}

catch(ArithmeticException e)

{Console.WriteLine(“Исключение перехвачено”);}

}

}

/*

Result:

Исключение перехвачено

Press any key to continue

*/

В примере 9.10.2 потенциально опасное деление на нуль охвачено try-блоком, а catch-блок перехватил выброшенное исключение типа ArithmeticException и выдал на консоль сообщение. Программа завершилась не аварийно.

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

Пример 9.10.3. Вложение исключений.

///////////////

// Java или J#

package cjLecExc_3a;

public class Exc

{

public static void main ( )

{

try

{

First ( );

}

catch (ArithmeticException e)

{System.out.println (e+" First");}

}

static void First ( )

{

Second ( );

}

static void Second ( )

{

int x, y, z;

try

{

x= 5; y= 0; z= x/y;

System.out.println ("z= "+z);

}

catch(ArithmeticException e)

{System.out.println (e+" Second");}

}

}

/*

Result:

java.lang.ArithmeticException: / by zero Second

Press any key to continue

*/

Программа примера 9.10.3 при выбросе исключения перехватила ближайший catch-блок функции Second(). Но если закомментировать try-catch-конструкцию в функции Second(), то сработает try-catch-конструкция, размещенная в функции First().

Результаты работы этой программы показывают, что при наличии соответствующего блока catch исключение не завершает аварийно всю программу, а завершает аварийно только функцию, в которой оно выброшено.

Пример 9.10.4 иллюстрирует необходимость применения исключения для выявления правильности вводимых данных в текстовый редактор. Программа проверяет, какое число было введено в редактор: положительное или отрицательное. После ввода числа и нажатия на кнопку в редакторе появляется слово positive или negative. Если введено не число, то в редакторе добавляется строка Error! Enter the correct number.

Пример 9.10.4. Обработчик кнопки использует исключение.

///////////////

// Java и J#

import java.awt.*;

import java.awt.event.*;

public class CTextBox extends Frame // Класс прикладного окна

{

TextField tB; // Редактор

Button b; // Кнопка

public CTextBox( ) // Конструктор

{

setTitle ("TestNumber"); // Установить заголовок прикладного окна

setSize (300, 200);

this.setBackground (Color.lightGray);

setLayout (null);

tB= new TextField ( ); // Создать редактор

tB.setLocation (10, 30); // Разместить редактор

tB.setSize (250, 20); // Установить размер

tB.setText ("Enter the number"); // Установить текст в редакторе

add (tB); // Добавить редактор в фрейм

b= new Button ("OK"); // Создать кнопку

b.setLocation (10, 50); // Разместить кнопку

b.setSize (40, 30); // Установить размер кнопки

add (b); // Добавить кнопку к фрейму

// Подписать слушателя на событие кнопки

b.addActionListener (new ActionListener ( )

{

public void actionPerformed (ActionEvent aE)

{

try

{

int n=Integer.parseInt (tB.getText());

if(n<0) tB.setText ("negative");

else tB.setText ("positive");

}

catch (NumberFormatException e)

{

tB.setText (tB.getText () +

" Error! Enter the correct number");

}

}

});

this.addWindowListener (new WindowAdapter ( )

{

public void windowClosing (WindowEvent wE)

{

System.exit (0);

}

});

}

public static void main ( ) // Главная функция

{

CTextBox cT= new CTextBox ( );

cT.show ( );

}

}

///////////////

C#

using System;

using System.Drawing;

using System.Windows.Forms;

class CTextBox : Form // Класс прикладного окна

{

TextBox tB; // Редактор

Button b; // Кнопка

public CTextBox( ) // Конструктор

{

Text="TestNumber"; // Установить заголовок прикладного окна

tB= new TextBox ( ); // Создать редактор

tB.Location= new Point (10, 30);// Разместить

tB.Size= new Size (250, 20); // Установить размер

tB.Text= "Enter the number"; // Установить текст в редакторе

this.Controls.Add (tB); // Добавить редактор в форму

b= new Button (); // Создать кнопку

b.Text= "OK"; // Установить название кнопки

b.Location= new Point (10, 50); // Разместить кнопку

b.Size= new Size (40, 30); // Установить размер кнопки

Controls.Add (b); // Добавить кнопку в форму

b.Click += new EventHandler (But); // Подписать обработчик

}

private void But (Object obj, EventArgs a)

{

string st= tB.Text;

try

{

int n=System.Convert.ToInt32 (st);

if(n<0) tB.Text= "negative";

else tB.Text= "positive";

}

//catch (Exception e)

catch (FormatException e)

{

tB.Text= tB.Text + " Error! Enter the correct number";

}

}

static void Main ( ) // Главная функция

{

CTextBox cT= new CTextBox ( );

Application.Run (cT);

}

}

///////////////

// C++/CLI

#include "stdafx.h"

#using <System.Drawing.dll>

#using <System.Windows.Forms.dll>

using namespace System;

using namespace System::Windows::Forms;

using namespace System::Drawing;

ref class CTextBox : Form // Класс прикладного окна

{

TextBox ^tB; // Редактор

Button ^b; // Кнопка

public:

CTextBox( ) // Конструктор

{

Text="TestNumber"; // Установить заголовок прикладного окна

tB= gcnew TextBox ( ); // Создать редактор

tB->Location= *gcnew Point (10, 30); // Разместить

tB->Size= *gcnew Drawing::Size (250, 20); // Установить размер

tB->Text= "Enter the number"; // Установить текст в редакторе

this->Controls->Add (tB); // Добавить редактор в форму

b= gcnew Button (); // Создать кнопку

b->Text= "OK"; // Установить название кнопки

b->Location= *gcnew Drawing::Point (10, 50); // Разместить кнопку

b->Size= *gcnew Drawing::Size (40, 30); // Установить размер

Controls->Add (b); // Добавить кнопку в форму

// Подписать обработчик

b->Click += gcnew EventHandler (this, &CTextBox::But);

}

private:

void But (Object ^obj, EventArgs ^a)

{

String ^st= tB->Text;

try

{

int n=System::Convert::ToInt32 (st);

if(n<0) tB->Text= "negative";

else tB->Text= "positive";

}

//catch (Exception e)

catch (FormatException ^e)

{

tB->Text= tB->Text + " Error! Enter the correct number";

}

}

};

void main ( )

{

Application::Run (gcnew CTextBox ( )); // Выполнить

}

C# и C++/CLI. Обработчик But() кнопки извлекает строку из редактора текста, применив свойство Text редактора. В блоке try-catch осуществляется преобразование извлечённой строки в целое число с помощью статической функции ToInt32() класса Convert. Если символы преобразуемой строки не являются цифрами, то во время преобразования будет выброшено исключение типа FormatException и в текстовом редакторе появится строка Error! Enter the correct number. Иначе положительное число в поле редактора заменится на слово positive, а отрицательное на negative.

Java и J#. На событие кнопки с помощью функции addActionListener() подписан объект анонимного класса ActionListener адаптера с обработчиком actionPerformed(). Обработчик в блоке try-catch извлекает из объекта tB редактора строку, используя статическую функцию parseInt() класса Integer и свойство getText() редактора. Результат работы программы совпадает с результатом работы программы на языке C#.

Обратите внимание, что в теле конструктора CTextBox( ) на языке Java аргумент функции setLayout (null) установки менеджера расстановки равен null, поэтому размещение редактора и кнопки в окне осуществляется не менеджером, а программистом с помощью свойств setLocation(), setSize() и setText().

Рис. 9.10.4. Прикладное окно приложения примера 9.10.4 после ввода положительного числа и нажатия на кнопку

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]