В чем суть finally block В Java?

Я думаю о следующих примерах; но не мог понять, в чем важность блока finally. Можете ли вы сказать мне разницу в выполнении этих двух образцов кода? Также может быть полезен пример из реальной жизни.

Пример 1:

    try{
       // some code 1
    }catch(Exception ex){
       // print exception   
    }finally{
       // some code 2            
    }

Пример 2:

    try{
      // some code 1
    }catch(Exception ex){
      // print exception   
    }
    // some code 2

7 ответов


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

это следующий фрагмент печатает "Finally!", а не "What about me???":

    try {
        throw null;     // throws NullPointerException!
    } catch (Exception e) {
        int oops = 1/0; // throws ArithmeticException!
    } finally {
        System.out.println("Finally!"); // still gets executed!
    }
    System.out.println("What about me???"); // doesn't get executed!

вообще говоря,finally на try блок практически всегда запускается на выполнение. Нет такой гарантии для любого кода, следующего за try блок.


а что, если мой catch блок просто print заявление?

есть еще никакой гарантии это не throw что-то. Что-то все равно может пойти не так, например, в конструкции для подробного сообщения об исключении.

даже если вы приложите все усилия, гарантируйте, что catch код "безопасный" и код после try оператор всегда будет выполняться, тогда вопрос становится "почему?". Почему не finally но тогда так старайтесь воспроизвести его семантику?

finally семантика гарантирована, не требуя никакого бремени доказательства ни от автора, ни от читателя кода. Именно из-за этого, это идиоматическое использовать finally блок для установки обязательного кода "очистки". Используя finally гарантирует правильность и увеличивает и writability и считываемость.


на finally блок выполняется, даже если, например,Error бросается, который не пойман catch блок в вашем примере. Таким образом, вы можете поместить код очистки в finally блок, который должен быть запущен всегда, независимо от исхода операции в try и catch блоки.

обратите внимание, что обычно catch блоки catch более конкретные типы исключений - часто только проверенные исключения, поэтому в большинстве случаев разница между двумя кода примеры выше очень определенные.

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

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

использовать finally блок для очистки и запуска любого кода, который должен выполняться, было ли создано исключение (и поймано) или нет. Это включает код, который у вас есть в catch блок.


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


обратите внимание, что вы можете даже попробовать-ваще без улова:

try{
   // some code 
}finally{
   // cleanup code
}

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


в случае, если операторы в try block бросают непроверенные исключения, наконец, блок будет выполнен, позволяя программисту предпринимать соответствующие действия.


В РЕАЛЬНОЙ ЖИЗНИ, блок finally используется для закрытия ресурсов, даже если возникает исключение. Например, при чтении (или записи) файла, при доступе к базе данных и т. д.

public void readFile(String fileName) {
    FileReader fr;
    BufferedFileReader bfr;

    try {
        fr = new FileReader(fileName);
        bfr = new BufferedFileReader(fr);
        // ...
    } catch (IOException ioe) {
        // ...
    } finally {
        // TO ENSURE THAT THE READERS ARE CLOSED IN ALL CASES
        if (bfr != null) { 
            try {
                bfr.close();
            } catch (IOException ignoredIOE) {}
        }
        if (fr != null) { 
            try {
                fr.close();
            } catch (IOException ignoredIOE) {}
        }
    }
}