Вам действительно нужен блок "наконец"
есть 3 перестановки попытки...поймать...блок finally в Java.
- попробовать...лови
- попробовать...поймать...наконец-то
- попробовать...наконец-то
после выполнения блока finally управление переходит к следующей строке после блока finally. Если я удалю блок finally и перемещу все его операторы в строку после попытки...блок catch, будет ли это иметь тот же эффект, что и их в конечном блоке?
9 ответов:
Я думаю, что willcode ближе всего подходит к выражению ключевого момента здесь, и, вероятно, все это означает, но не ясно.
проблема в том, что действительно что-то очень не так с тем, что вы спрашиваете: "если я напишу все утверждения после блока catch вместо того, чтобы записывать их в finally block, тогда будет ли что-то не так?"
Если вы пишете все операторы после блока catch, то вы подразумеваете, что
1) Вы всегда будете поймать исключение.
2) вы всегда будете переходить к следующим операторам после того, как вы поймаете исключение.
Это означает, что вы всегда будете продолжать выполнение "нормально" после исключения, которое, как правило, что-то вы никогда на самом деле хотите делать.
исключения должны быть просто исключительными. Если вы действительно можете обрабатывать исключение, всегда лучше написать свой код для рассмотрения этих условий в первую очередь и не приводит к исключению вообще. Если вы следуете этой модели, то исключения действительно являются исключительными-условия, которые вы не могли предвидеть или в лучшем случае не исправить. На самом деле не предвидеть то, что вы должны работать. это означает, что в целом вы не можете обрабатывать истинные исключения, что также означает, что вы не должны просто продолжать выполнение, часто вы заканчиваете приложение вместо этого.
что обычно делается это вы разрешить ошибку для распространения резервного копирования стека вызовов. Некоторые говорят, что это делается на случай, если кто-то выше в цепи может быть в состоянии справиться с этим. Я бы сказал, что по существу никогда не происходит, есть две реальные цели для этого. Один это может быть что-то пользователь может исправить, если он есть. Таким образом, вы распространяете ошибку обратно, пока не доберетесь до того места, где вы можете сообщить об этом пользователю. Или два пользователь не может исправить это, но вы хотите получить весь стек вызовов для отладки. Тогда вы поймаете его на сверху красиво не получится.
finally блок должен теперь иметь больше смысла для вас. Как все говорят, он всегда работает. Самое четкое использование, наконец, действительно в попытке... наконец-то заблокировать. То, что вы сейчас говорите, если код работает нормально, отлично. Нам все еще нужно сделать некоторую очистку, и, наконец, всегда выполняется, тогда мы двигаемся дальше. Но если возникает исключение, нам теперь действительно нужен этот последний блок, потому что нам все еще может понадобиться сделать некоторую очистку, но мы больше не ловим исключение здесь, поэтому мы больше не будем двигаться дальше. Окончательно блок необходим для того чтобы обеспечить что чистка вверх происходит.
идея исключения всегда останавливает выполнение может быть трудно для кого-то, чтобы понять, пока они не имеют определенное количество опыта, но это на самом деле способ всегда делать вещи. Если произошла ошибка, либо она была настолько незначительной, что вы должны были ее учесть, или же просто все больше и больше ошибок ждут, чтобы произойти вниз линия.
"глотание" ошибок-ловить их и двигаться дальше-это худшее, что вы можете сделать, потому что ваша программа становится непредсказуемой, и вы не можете найти и исправить ошибки.
хорошо написанный код будет содержать столько же попыток ... наконец блоки, как это необходимо, чтобы убедиться, что ресурсы всегда освобождаются независимо от результата. Но хорошо написанный код обычно содержит лишь небольшое количество попыток ... блоки catch, которые существуют в основном для разрешения сбоя приложения как изящно, насколько это возможно, или отложить до пользователя, что означает, по крайней мере, всегда передавать сообщение пользователю и т. д. Но вы обычно не просто ловите ошибку и продолжаете идти.
Я знаю, что это очень старый вопрос, но я столкнулся сегодня, и я был смущен данными ответами. Я имею в виду, что все они верны, но все отвечают на теоретическом или даже философском уровне, когда есть очень простой практический ответ на этот вопрос.
если вы поместите return, break, continue или любое другое ключевое слово java, которое изменяет последовательное выполнение кода внутри блока catch (или даже попробовать блок), заявления внутри наконец блок все равно будет выполнен.
например:
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 гарантированно будет выполнен, даже если возникает исключение. Вы используете их для выполнения необходимой очистки, как закрытие потоков. Код после блока finally может никогда не быть достигнут.
из java учебник
блок finally всегда выполняется, когда попробуйте заблокировать выходы. Это гарантирует, что блок finally выполняется даже если непредвиденное исключение. Но наконец, полезно больше, чем просто обработка исключений - это позволяет программист, чтобы избежать очистки код случайно обошла возвращение, продолжение или перерыв. Сдачи код очистки в блоке finally всегда хорошая практика, даже когда нет исключений не предвидится.
если я понимаю вопрос, вы спрашиваете, в чем разница между:
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 ищет исключение обработчик.
EDIT
отвечая на ваш комментарий, насчет:
Foo f = new Foo(); try { f.bar(); } catch (Exception ex) { // ... } f.baz();вы правы, что если
catchблок не перестраивает исключение или возвращает из метода, указывающего на сбой, а затемf.baz()вызывается независимо от того, было исключение. Однако даже в этом случаеfinallyблок служит в качестве документации,f.baz()используется для очистки.больше важно отметить, что тот факт, что исключение было брошено обычно важно, так что очень трудно написать код, который продолжает делать все, что он делал, не зная, что исключение было брошено. Бывают случаи, что исключения указывают на глупые вещи, которые вы можете игнорировать, и в этом случае вы должны проглотить исключение. Однако чаще всего вы хотите сигнализировать об ошибке, либо повторно создавая исключение (или бросая другое исключение), либо возвращаясь из метода с ошибкой код.
, еслиf.bar()предполагается преобразоватьStringдоDouble, и на отказ его бросает!--46-->NumberFormatException, то код послеtryблок, вероятно, должен знать, чтоStringфактически не был преобразован вDouble. И, таким образом, в целом вы не захотите продолжать послеcatchблок. Вместо этого вы захотите сигнализировать об ошибке. Это известно как "прервать при сбое" (по сравнению с "возобновить при сбое", который, вероятно, следует называть "путаться после неудачи со скрещенными пальцами").кроме того, в особых случаях вы можете быть в состоянии колебаться. Например,
catchблок может установить соответствующийDoubleдоDouble.NaNкоторый разработан специально для правильного распространения ошибок в математических выражениях. Даже в этом случаеfinallyблок служит в качестве документации,f.baz()участвует в какой-то очистки.
блок finally содержит строки кода, которые должны выполняться независимо от того, было ли поймано исключение или нет. Даже если вы решили остановить выполнение кода в этом методе. Таким образом, код после t-c-f может не выполняться, но, наконец, код "гарантирован" (гарантирован в смысле немедленного сбоя, нарушающего неуправляемую ошибку).
Да, было бы что-то очень критично неправильно.
и это означает, что ваш код будет работать только если есть ошибка.
инструкции внутри
finallyвсегда запускайте, независимо от того, было ли вызвано исключение. В этом-то все и дело.
наконец блок, особенно используемый во время предотвращения исключений. Если какая-либо ошибка выполнения происходит, программа может привести к завершению. Поэтому в это время он будет вызывать finally block Перед тем, как завершить программу. Обычно "finally" содержит инструкции закрытия соединения, операции сохранения и ввода файла, операции закрытия вывода.
Если ваш код никогда не выдает исключение, или вы потребляете все исключения, которые будут правильными. Это не всегда происходит.
два месяца назад я написал пост для причина 'наконец' в try/catch.
известно, что ссылка становится на пути редактирования в стиле Вики моды здесь.
это самодостаточный пост, который просто копирует его, не будет работать, так как вы пропустите следующий комментарий, который также добавляет ценность.
Comments