В чем суть блока finally в Java? - PullRequest
8 голосов
/ 30 июня 2010

думаю на следующих примерах; но не мог понять, какова важность блока 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 ]

17 голосов
/ 30 июня 2010

Существует большая разница в двух представленных вами фрагментах, например, когда сам блок 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 гарантирует правильность и улучшает как удобочитаемость, так и читабельность.

8 голосов
/ 30 июня 2010

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

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

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

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

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

1 голос
/ 30 июня 2010

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

0 голосов
/ 30 июня 2010

В реальной жизни блок 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) {}
        }
    }
}
0 голосов
/ 30 июня 2010

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

0 голосов
/ 30 июня 2010

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

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

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

...