Я думаю на следующих примерах; но не мог выяснить, каков важность наконец блок. Можно ли сказать мне различие выполнения этих двух примеров кода? Также реальный пример может быть полезным.
Демонстрационный 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
В двух представленных вами фрагментах есть большая разница, например когда сам блок catch
генерирует исключение, блок finally
по-прежнему будет выполняться в соответствии с его семантикой.
Это следующий фрагмент печатает «Наконец-то!»
, но не «Что насчет меня ???»
:
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
- это всего лишь простой оператор
По-прежнему нет гарантии , что он не выбросит
что-то. Что-то все еще могло пойти не так, например, конструкция для подробного сообщения об исключении.
Даже если вы сделаете все возможное, чтобы гарантировать, что код catch
является «безопасным», а код, следующий за оператором try
, всегда будет выполняться, тогда возникает вопрос: «Почему? ". Зачем избегать finally
, а затем так стараться воспроизвести его семантику?
finally
семантика гарантирована, не требуя бремени доказательства ни от автора, ни от читателя кода. Именно из-за этого идиоматично использовать блок finally
для установки обязательного кода «очистки». Использование finally
гарантирует правильность и улучшает как возможность записи, так и читаемость.
это полезно, когда мы хотим освободить ресурсы, которые мы использовали в блоке try. Так что единственное место, где можно их выполнить, ни в коем случае не пропуская, - это finally block. Поскольку, если возникает исключение, java не выполняет код сразу после этого. он сразу переходит к блоку захвата.
Блок finally
выполняется, даже если, например, выдается ошибка
, которая не перехватывается блоком catch
в вашем примере. Таким образом, вы можете поместить код очистки в блок finally
, который должен запускаться всегда , независимо от результата операций в try
и catch.
блоков.
Обратите внимание, что обычно блоки catch
перехватывают более конкретные типы исключений - часто только проверенные исключения - поэтому в большинстве случаев разница между двумя приведенными выше примерами кода очень очевидна.
Обновление: вы можете сказать, что ваш блок catch
никогда не может генерировать исключение, поэтому finally
не требуется.Однако обратите внимание на две вещи:
блок catch
, запомнит ли помещать код очистки после него в блок finally
? try-catch-finally
- это идиома программирования что помогает людям, читающим код, понять, что происходит. Если вы не используете общепринятую идиому, вы рискуете непонимание, а значит, и ошибки в долгосрочной перспективе. В реальной жизни блок 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) {}
}
}
}
Вы используете блок finally
для очистки и запуска любого кода, который должен выполняться независимо от того, было создано (и перехвачено) исключение или нет. Сюда входит код из блока catch
.
В случае, если операторы в блоке try вызывают непроверенные исключения, блок finally выполняется, позволяя программисту предпринять соответствующие действия.
Обратите внимание, что вы можете даже попробовать-finally без уловки:
try{
// some code
}finally{
// cleanup code
}
Таким образом, примером может быть метод, который хочет распространять исключения на вызывающую сторону, но все еще нуждается в коде очистки, например выпуская взгляд.