
- •9. Библиотека .Net Framework и библиотеки языка Java
- •9.1. Приложение
- •9.2. Классы, объекты и элементы приложения
- •9.3. Простейшие приложения
- •9.4. Сообщения Windows, события и делегаты
- •9.4.1. Обработка событий мыши на языке c#
- •9.4.3. Обработка событий мыши на языке Java с использованием предопределённого обработчика mouseDown
- •9.4.4. Связь события с несколькими объектами на языке c#
- •Ещё раз о событиях и уведомлении в языке Java
- •9.5.1. Обработка событий элементов интерфейса пользователя в языке Java
- •Обработка событий мыши на языке Java, используя интерфейс MouseListener
- •9.5.3. Обработка событий мыши на языке Java, используя классы адаптеров
- •9.5.4. Обработка событий мыши на языке Java, используя внутренние классы адаптеров и анонимные классы
- •9.5.5. Обработка события закрытия окна
- •Графика
- •9.6.1. Графические объекты
- •Прямоугольник
- •Класс Pen
- •Класс SolidBrush
- •Класс Font
- •Класс Graphics
- •9.7. Событие Paint и его обработчик
- •9.8. Управляющие элементы
- •Класс Button
- •Классы TextBox и TextField
- •Классы UserControl и Panel
- •9.9. Дочерние окна
- •9.10. Исключения
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 после ввода положительного числа и нажатия на кнопку