Главная » Java » finallу Java

0

Предложение finally конструкции tгу предлагает механизм передачи управления определенному фрагменту кода, не зависящий от того, было выброшено исключение в процессе выполнения кода блока try или нет. Обычно блок finally используется для осуществления операций очистки внутреннего состояния объекта или высвобождения ресурсов, не связанных со свободно распределяемой памятью, таких как, например, дескрипторы открытых файлов, хранимые в Локальных переменных. Ниже приведен при мер метода, который обеспечивает поиск строки в файле и закрытие последнего даже в случае возникновения ошибки.

public boolean searchFor(string file, string word) throws streamException

{

Stream input = null;

try {

input = new stream(file);

 while (!input.eof())

if (input.next().equals(word))

 return true;

return false; // Строка не найдена }

 finally {

if (input!= null)

input.close;

}

}

Если выполнение оператора new завершится неудачей, в поле input останется исходное значение null, в противном случае переменной input будет присвоена ссылка, которая Указывает на объект, представляющий открытый файл. При выполнении блока finally поток input зарывается только в том случае, если ранее он был открыт. Независимо от исхода выполнения операций блока try, код finally гарантирует, что поток будет закрыт, обеспечивая тем самым целостность данных и предотвращая расходование ограниченного ресурса дескрипторов открытых файлов. В объявлении метода searchFor упомянут тип исключений StreamException, поэтому любые генерируемые методом исключения будут передаваться для обработки внешнему коду, вызывающему searchFor, после выполнения блока finally (если исключение StreamException возникнет при обращении к close, оно также будет передано для обработки во внешний код).

Существуют два основных способа правильно го использования блока finally. Вначале рассмотрим общую картину. Мы выполняем два действия – назовем их до и после; если произошло до, должно произойти и после – независимо от факта выполнения в промежутке между ними других действий и от того, успешны ли эти действия либо они привели к выбрасыванию исключения. Первый способ применения finally можно про иллюстрировать следующим образом:

до();

 try {

// другие действия }

finally {

после() ;

}

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

В рассмотренном выше примере searchFor реализован второй способ применения finally. В этом случае подразумевается, что метод до возвращает некоторое значение, которое помогает проверить, выполнен метод успешно или нет. Метод после в блоке finally вызывается только в случае благополучного завершения операций в теле до:

Object val = null;

 try {

val = до();

// другие действия }

finally {

if (val != null)

 после();

}

На сей раз мы могли бы вновь вынести до за пределы блока tгу и избавиться 01 выражения if в finally. Преимущества размещения вызова до именно внутри tгу заключаются в том, что нам предоставляется возможность с помощью единой конструкции try-catch обрабатывать все исключения, которые могут быть вы· брошены методом до и остальными инструкциями блока, помеченными комментарием другие действия. Иными словами, если до находится внутри блока try, мы можем обойтись одним набором предложений catch; в противном случае для отлова исключений, генерируемых методом до, нам пришлось бы прибегнуть к помощи внешней конструкции try … catch. Ситуация усугубляется, если метод ДО и другие действия способны выбрасывать исключения одних и тех же типов – при выполнении операций ввода-вывода такая ситуация довольно типична, – а нам к тому же желательно после некоторой обработки объектов исключений передавать их дальше во внешний код. Исключения, сгенерированные инструкциями, будут обрабатываться дважды, и блокам catch придется каким-то образом следить за развитием событий и распознавать, что есть что.

Предложения finally используются и в тех случаях, когда необходимо осуществить ряд завершающих операций после выполнения инструкций break Continue или return, – вот почему нередко применяются такие конструкции try, в которых отсутствуют предложения catch. При выполнении любой команды передачи управления во внешний блок сначала выполняются инструкции соответствующих предложений finally. Не существует способов покинуть конструкцию tгу, обойдя присутствующий в ней блок finally.

в рассмотренном примере блок finally выполняется в том числе и после нормального завершения кода блока try посредством инструкций return. Один из наиболее веских доводов в пользу применения команды goto в других языках программирования связан с необходимостью выполнения некоторых вспомогательных операций после того, как завершен (успешно или с ошибками) Основной блок кода. В нашем примере подобные гарантии обеспечивает finally – файл благополучно закрывается и при успешном завершении блока try командой return, и в том случае, когда при выполнении, файловых операций выбрасывается исключение; поэтому у нас нет причин сожалеть о том, что команда goto в Java не поддерживается.

При передаче управления в блок finally предварительно сохраняется информация о причине окончания выполнения блока try – код был исчерпан естественным образом либо принудительно завершен с помощью одной из управляющих инструкций, таких как return, или сгенерированного исключения. Эта информация восстанавливается в момент выхода из блока finally. Если, Однако, код finally обладает собственными полномочиями по передаче управления во внешний блок посредством инструкций break или return либо выбрасывания исключения, исходная причина "забывается" и замещается новой. Проиллюстрируем сказанное следующим примером:

try {

// ЧТО-ТО ПРОИСХОДИТ…

return 1;

} finally {

return 2;

}

После выполнения кодом try команды return блоку finally передается управление и информация о причине завершения tгу – инструкция return возвратила значение 1. :Код finally, в свою очередь, также выполняет команду return, но теперь она возвращает уже другое значение – 2, и исходное "намерение" системы заменяется новым. Если в процессе выполнения кода try будет выброшено исключение, итогом все равно окажется, разумеется, инструкция return 2;. Но если бы блок finally не содержал этой инструкции, первоначальная цель – "возвратить с помощью команды return значение 1" – была бы реализована.

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

  • Комментарии