a2e98898

Для чего нужно finally?


В языках без сборщика мусора и без автоматического вызова деструктора [54], finally очень важно, потому что оно позволяет программисту гарантировать освобождение памяти независимо от того, что случилось в блоке try. Но Java имеет сборщик мусора, так что освобождение памяти, фактически, не является проблемой. Также, язык не имеет деструкторов для вызова. Так что, когда вам нужно использовать finally в Java?

finally необходимо, когда вам нужно что-то установить, отличное от блока памяти, в его оригинальное состояние. Это очистка определенного вида, такое как открытие файла или сетевого соединения, рисование на экране или даже переключение во внешний мир, как смоделировано в следующем примере:

//: c10:OnOffSwitch.java

// Почему используется finally?

class Switch { boolean state = false; boolean read() { return state; } void on() { state = true; } void off() { state = false; } } class OnOffException1 extends Exception {} class OnOffException2 extends Exception {}

public class OnOffSwitch { static Switch sw = new Switch(); static void f() throws OnOffException1, OnOffException2 {} public static void main(String[] args) { try { sw.on(); // Код, который может выбросить исключение...

f(); sw.off(); } catch(OnOffException1 e) { System.err.println("OnOffException1"); sw.off(); } catch(OnOffException2 e) { System.err.println("OnOffException2"); sw.off(); } } } ///:~

Цель этого примера - убедится, что переключатель выключен, когда main( ) будет завершена, так что sw.off( ) помешена в конце блока проверки и в каждом обработчике исключения. Но возможно, что будет выброшено исключение, которое не будет поймано здесь, так что sw.off( ) будет пропущено. Однако с помощью finally вы можете поместить очищающий код для блока проверки только в одном месте:

//: c10:WithFinally.java

// Finally гарантирует очистку.

public class WithFinally { static Switch sw = new Switch(); public static void main(String[] args) { try { sw.on(); // Код, который может выбросить исключение...


OnOffSwitch.f(); } catch(OnOffException1 e) { System.err.println("OnOffException1"); } catch(OnOffException2 e) { System.err.println("OnOffException2"); } finally { sw.off(); } } } ///:~

Здесь sw.off( ) была перемещена только в одно место, где она гарантировано отработает не зависимо от того, что случится.

Даже в случае исключения, не пойманного в этом случае набором предложений catch, finally будет выполнено прежде, чем механизм обработки исключений продолжит поиск обработчика на более высоком уровне:

//: c10:AlwaysFinally.java

// Finally выполняется всегда.

class FourException extends Exception {}

public class AlwaysFinally { public static void main(String[] args) { System.out.println( "Entering first try block"); try { System.out.println( "Entering second try block"); try { throw new FourException(); } finally { System.out.println( "finally in 2nd try block"); } } catch(FourException e) { System.err.println( "Caught FourException in 1st try block"); } finally { System.err.println( "finally in 1st try block"); } } } ///:~

Вывод этой программы показывает что происходит:

Entering first try block Entering second try block finally in 2nd try block Caught FourException in 1st try block finally in 1st try block

Инструкция finally также будет исполнена в ситуации, когда используются инструкции break и continue. Обратите внимание, что наряду с помеченным break и помеченным continue, finally подавляет необходимость в использовании инструкции goto в Java.


Содержание раздела