Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых
[Назад]

Библиотека примеров приложений Java

Оглавление
Базовые типы

Замещающие типы
Без указателей
Массивы
Структурное программи-
рование

Обработка исключений
Возбуждение исключений
Классы обработки исключений
Блок finally
Строки String
Класс Math
Класс Vector
Класс Stack
Словарь на базе Hashtable
Словарь на базе Properties
Цифровые часы
Собственный класс
Наследование классов

Интерфейсы

Назад Вперед

1.9. Применение блока finally

В примере демонстрируются использование блока finally при обработке исключений.

Исходный текст примера

Архив проекта для Java WorkShop 2.0

Немного теории

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

Наилучшее применение для блока finally - освобождение ресурсов, заказанных программой перед возникновением исключений. Хотя система сборки мусора автоматически освобождает ненужную более оперативную память, открытые потоки, например, следует закрывать явным образом при помощи метода close.

Описание примера

В нашем примере мы создаем цикл ввода целых чисел. После выполнения операции деления числа 100 на введенное число полученный результат записывается в буферизованный выходной поток.

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

Так как программа работает с потоками, она импортирует класс java.io.*. Дополнительно для разбора введенной текстовой строки мы используем класс java.util.*:

import java.io.*;
import java.util.*;

В главном классе программы мы определили статическое поле os класса DataOutputStream:

static DataOutputStream os;

В него будет записана ссылка на выходной поток.

Создание потока выполняется следующим образом:

try
{
  os = new DataOutputStream(
    new BufferedOutputStream(
      new FileOutputStream("log.txt")));
}
catch(Exception ex)
{
  System.out.println(ex.toString()); 
}

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

В нашем примере мы намеренно применили буферизованный поток, так как если такой поток не закрыть перед завершением программы, данные не будут переписаны из буфера в файл.

Цикл ввода чисел и записи результата вычислений в поток мы полностью разместили в блоке try. В сокращенном виде этот цикл представлен ниже:

try
{
  while(true)
  {
    . . .
  }
}
catch(Exception ex)
{
  System.out.println(ex.toString()); 
}
finally
{
  try
  {
    System.out.println("close"); 
    os.close();
  }
  catch(Exception ex)
  {
    System.out.println(ex.toString()); 
  }
}

Если в результате возникновения исключения цикл аварийно завершается, блок finally закрывает поток os. Заметим, что этот поток закрывается и в случае нормального завершения цикла, так как блок finally выполняется в любом случае - произошло исключение, или нет.

Теперь о том, что происходит внутри цикла.

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

byte bKbd[] = new byte[256];
String szStr = "";
 
int iCnt = System.in.read(bKbd);
szStr = new String(bKbd, 0, iCnt);

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

Для удаления из строки символов \r и \n мы создаем объект класса StringTokenizer. Через второй параметр конструктору передается строка символов-разделителей:

StringTokenizer st;
st = new StringTokenizer(szStr, "\r\n");

При помощи метода nextElement мы извлекаем нужную нам часть строки и затем записываем ее в поле szStr:

szStr = 
  new String((String)st.nextElement());

Далее строка преобразуется в значение типа int:

Integer intVal = new Integer(szStr);
int i;
i = intVal.intValue();

Если в результате получается число 777, работа цикла завершается нормальным образом:

if(i == 777)
  break;

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

i = 100 / i;

Очевидно, что при вводе нулевого значения должно произойти исключение. При этом управление будет передано блоку catch, а затем блоку finally.

В том случае, когда деление произошло успешно, результат записывается в выходной поток и выводится на консоль:

os.writeBytes(i + " ");
System.out.println(i + " ");

Назад Вперед

[Назад]