Вам действительно нужен блок "finally" - программирование
Подтвердить что ты не робот

Вам действительно нужен блок "finally"

Есть 3 перестановки try... catch... finally block в java.

  • Try... Catch
  • попробовать... поймать... наконец-то
  • попробовать... наконец,

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

4b9b3361

Ответ 1

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

Проблема в том, что есть что-то очень неправильное в том, что вы спрашиваете: "Если я напишу все инструкции после блока catch вместо того, чтобы записывать их в блок finally, тогда будет ли что-то не так?"

Если вы пишете все инструкции после блока catch, то вы подразумеваете, что

1) Вы всегда поймаете исключение.

2) После того, как вы поймаете исключение, вы всегда будете продолжать следующие инструкции.

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

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

Что обычно делается, вы разрешаете ошибке распространять резервную копию стека вызовов. Некоторые говорят, что это делается на случай, когда кто-то выше в цепочке сможет справиться с этим. Я бы сказал, что по существу никогда не бывает, есть две реальные цели для этого. Один из них может быть чем-то, что пользователь может исправить, если он есть. Таким образом, вы распространяете ошибку, пока не дойдете до того, где вы можете сообщить об этом пользователю. Или два, пользователь не может исправить это, но вы хотите получить весь стек вызовов для отладки. Тогда вы поймаете его наверху, чтобы терпеть неудачу изящно.

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

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

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

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

Ответ 2

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

Из java tutorial

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

Ответ 3

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

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

Например:

public void myFunc() {

    double p = 1.0D;
    String str = "bla";
    try{
        p = Double.valueOf(str);
    }
    catch(Exception ex){
        System.out.println("Exception Happened");
        return;  //return statement here!!!
    }finally{
        System.out.println("Finally");
    }
    System.out.println("After finally");
}

при выполнении этого кода будет напечатан:

Exception Happened 
Finally

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

Ответ 4

Если я понимаю вопрос, вы спрашиваете, в чем разница между:

try {
    Foo f = new Foo();
    f.bar();
}
finally
{
    Foo.baz();
}

и

// This doesn't actually compile because a try block needs a catch and/or finally block
try {
    Foo f = new Foo();
    f.bar();
}
Foo.baz();

Или, более вероятно:

Foo f = new Foo();
f.bar();
Foo.baz();

Разница в том, что если либо new Foo(), либо f.bar() выдают исключение, блок finally будет выполнен в первом случае, но Foo.baz() не будет выполнен в двух последних случаях: вместо элемент управления пропустит Foo.baz(), в то время как JVM ищет обработчик исключений.


ИЗМЕНИТЬ

Отвечая на ваш комментарий, как насчет:

Foo f = new Foo();
try {
    f.bar();
}
catch (Exception ex)
{
    // ...
}

f.baz();

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

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

Например, если f.bar() предполагается преобразовать a String в Double, а при ошибке он выдает NumberFormatException, то код после блока try, вероятно, должен знать, что String фактически не преобразован в Double. И, таким образом, в общем случае вы не захотите продолжать работу после блока catch. Вместо этого вы захотите сигнализировать о сбое. Это называется "прерывание при отказе" (по сравнению с "возобновлением неудачи", которое, вероятно, следует называть "путаться после неудачи скрестив пальцы" ).

Кроме того, в особых случаях вы можете запутаться. Например, блок catch может установить соответствующий Double в Double.NaN, который специально разработан для корректного распространения ошибок в математических выражениях. Даже в этом случае блок finally служит документацией, в которой f.baz() участвует в какой-то очистке.

Ответ 5

Блок finally содержит строки кода, которые должны выполняться независимо от того, было ли обнаружено исключение. Даже если вы решите остановить выполнение кода в этом методе. Таким образом, код после t-c-f может не выполняться, но код finally "гарантирован" (гарантированно в том смысле, что он не сбой, сразу же нарушающий ошибку без обработки).

Ответ 6

Да, было бы очень критически неправильно.

Иными словами, ваш код будет работать только при наличии ошибки.

Заявления внутри finally всегда запускаются независимо от генерируемого исключения. Вот в чем смысл.

Ответ 7

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

Ответ 8

Если ваш код никогда не вызывает исключение, или вы потребляете все исключения, это будет правильно. Это не то, что всегда происходит.

Ответ 9

Два месяца назад я написал сообщение для причину "наконец" в try/catch.

Зная, что ссылка на пути редактирования в стиле вики здесь.

Это автономный пост, который просто копирует его, не будет работать, поскольку вы пропустите комментарий, который также добавит ценность.