89

There are 3 permutations of a try...catch...finally block in java.

  1. try...catch
  2. try...catch...finally
  3. try...finally

Once the finally block is executed, control goes to the next line after the finally block. If I remove the finally block and move all its statements to the line after the try...catch block, would that have the same effect as having them in the finally block?

gkrogers
  • 8,126
  • 3
  • 29
  • 36
Amit Kumar Gupta
  • 7,193
  • 12
  • 64
  • 90
  • 3
    This question has been answered before http://stackoverflow.com/questions/3354823/how-to-use-finally. So its a duplicate – Shervin Asgari Oct 05 '10 at 09:42
  • 1
    [Code in a finally block is guaranteed to run! Always! No exceptions!](http://thedailywtf.com/Articles/My-Tales.aspx) – badp Oct 05 '10 at 10:40
  • @Shervin, had you read both questions before marking it as duplicate – Amit Kumar Gupta Oct 12 '10 at 10:28
  • Possible duplicate of [how to use finally](https://stackoverflow.com/questions/3354823/how-to-use-finally) – Tony Danilov Mar 27 '18 at 13:16
  • Does this answer your question? [Why do we use finally blocks?](https://stackoverflow.com/questions/3421486/why-do-we-use-finally-blocks) – nawfal Oct 01 '21 at 12:56

9 Answers9

117

I know this is a very old question but I came across today and I was confused by the answers given. I mean, they are all correct but all answer on a theoretical or even philosophical level when there is a very straightforward practical answer to this question.

If you put a return, break, continue or any other java keyword that changes the sequential execution of code inside the catch block (or even try block), the statements inside the finally block will still be executed.

For example:

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");
}

when executed this code will print:

Exception Happened 
Finally

That is the most important reason for the existence of a finally block. Most answers imply it or refer to it on the sidelines but none of them is putting emphasis on it. I think because this is kind of a newbie question such a straightforward answer is very important.

Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79
Angelos Makrygiorgos
  • 1,382
  • 2
  • 8
  • 17
  • 8
    Thanks, this was the answer I was looking for. – muds Aug 06 '19 at 08:03
  • 2
    We need more engineers like you in this world. – pregenRobot Feb 13 '21 at 02:57
  • 1
    Another important change of sequential execution inside the `catch` block that might as well be stated explicitly is, indeed, an exception occurrence. `finally` will execute in case of any such secondary exception as well. – Jamesfo Jun 26 '22 at 16:00
52

I think willcode comes the closest to expressing the key point here, and probably everyone means it but are not clear.

The problem is there is indeed something very wrong with what you are asking: "If i write all the statements after catch block instead of writing them into finally block then then would there be anything wrong?"

If you write all the statements after the catch block, what you are implying is that

1) You will always catch the exception.

2) You will always continue on to the next statements after you catch the exception.

This implies that you will always continue the execution "normally" after an exception, which is generally something you never in fact want to do.

Exceptions should be just that - exceptional. If you can in fact handle an exception, it is always better to write your code to consider those conditions first and not lead to an exception at all. If you follow this model then exceptions are truly exceptional - conditions you could not anticipate or at most not fix. Really not anticipate is what you should work towards. This means in general you are unable to handle true exceptions, which also means you should not just continue execution, often you end the application instead.

What is normally done is you allow an error to propagate back up the call stack. Some say this is done on the off chance that someone higher up in the chain may be able to handle it. I would say that essentially never happens, there are two real purposes to do this. One it may be something the user can fix, if there is one. So you propagate the error back up until you get to where you can report it to the user. Or two, a user cannot fix it but you want to get the entire call stack for debugging. Then you catch it at the top to fail gracefully.

The finally block now should have more meaning to you. As everyone says it always runs. The clearest use of a finally is really in a try... finally block. What you are now saying is if the code runs fine, great. We still need to do some clean up and the finally always executes then we move on. But if an exception occurs, we now really need that finally block because we may still need to do some clean up, but we are no longer catching the exception here so we are not going to be moving on anymore. The finally block is essential to ensure that clean up occurs.

The idea of an exception always halting execution may be hard for someone to grasp until they have a certain amount of experience, but that is in fact the way to always do things. If an error happened, either it was so minor you should have accounted for it to begin with, or else there are just more and more errors waiting to happen down the line.

"Swallowing" errors - catching them and moving on is the worst thing you can do because your program becomes unpredictable and you cannot find and fix bugs.

Well written code will contain as many try ... finally blocks as are necessary to make sure that resources are always released no matter the outcome. But well written code generally contain only a small number of try ... catch blocks that exist primarily to allow an application to fail as gracefully as possible, or defer to the user, which means at least always pass a message to the user etc. But you usually do not just catch an error and keep going.

Sisyphus
  • 4,181
  • 1
  • 22
  • 15
  • 12
    Your conclusion (1 and 2) is absolutely wrong - No, this question doesn't imply that he will always catch exception and/or he will always continue with consequent instructions. 1) Even if you don't catch exception, you still continue on the consequent lines unless you return from function; 2) If you don't return, no matter you proceed with try block or catch - you ALWAYS will continue with consequent instructions (if there are any), and that's correct, nothing's wrong here. I would've answered, that one can return during try - but finally still will be executed. That's the difference. – Giorgi Tsiklauri Jul 15 '17 at 17:24
  • @GiorgiTsiklauri You say execution will continue "Even if you don't catch an exception," but this is not always true--Do you mean no exception occurs at all? If so, you're not taking into account when there is an exception but it isn't one for which you have a catch statement. Finally would work well for that. "return during try" is definitely not the only reason finally exists. – Poikilos Jul 23 '19 at 13:02
  • I consent to @GiorgiTsiklauri 's comment. But I would like to add, that personally I find `finally` unnecessary. Just don't return in a catch block and put that code right after the catch block, if there is still some clean-up (or whatever) code to be run after either a successful operation or a not successfull operation. But i guess it is a matter of taste. (sim. early return vs. else) – ILCAI Sep 12 '22 at 21:17
47

The highlight is that a finally block is guaranteed to be executed even if an exception is raised and not caught. You then use the finally block, as a one time chance, to perform necessary clean-up like closing streams. The code after the finally block might never be reached.

From the java tutorial

The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

Valdi_Bo
  • 30,023
  • 4
  • 23
  • 41
willcodejavaforfood
  • 43,223
  • 17
  • 81
  • 111
13

If I understand the question, you're asking what's the difference between:

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

And:

// 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();

Or, more likely:

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

The difference is that if either new Foo() or f.bar() throw an exception, the finally block will get executed in the first case, but that Foo.baz() won't get executed in the last two cases: instead control will skip over Foo.baz() while the JVM looks for an exception handler.


EDIT

Responding to your comment, what about:

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

f.baz();

You are right that, assuming the catch block doesn't rethrow the exception, or return from the method indicating a failure occured, then f.baz() gets called regardless of whether there was an exception. Even in that case, however, the finally block serves as documentation that f.baz() is used for cleanup.

More importantly, the fact that an exception was thrown usually is important, so it's very hard to write code that continues on doing whatever it was doing without knowing that an exception was thrown. There are times that exceptions indicate silly things that you can ignore, and in that case you should swallow the exception. More often, however, you will want to signal failure, either by rethrowing the exception (or throwing a different exception) or returning from the method with an error code.

For example, if f.bar() is supposed to convert a String to a Double, and on failure it throws a NumberFormatException, then code after the try block probably needs to know that the String was not actually converted to a Double. And, so, in general you won't want to continue after the catch block. Instead, you'll want to signal failure. This is known as "abort on failure" (compared to "resume on failure," which probably should be called "muddle on after failure with your fingers crossed").

Except, in special cases you may be able to muddle on. For instance, the catch block could set the relevant Double to Double.NaN which is designed specifically to propagate errors correctly in math expressions. Even in that case, the finally block serves as documentation that f.baz() is involved in some kind of cleanup.

Max Lybbert
  • 19,717
  • 4
  • 46
  • 69
  • 1
    I was saying that try and catch both blocks ae present. Now what is the need of finally? Because if error has been caught and specific action has been taken then the next statement (either finally{} or the statement after catch{}) shall be executed. – Amit Kumar Gupta Oct 06 '10 at 07:21
  • @aticlestak: I've edited the article to hopefully answer your question. The case you describe turns on the philosophy about how to use exceptions. – Max Lybbert Oct 06 '10 at 14:03
3

The finally block contains lines of code that should be executed regardless whether an exception has been caught or not. Even if you decide to stop code running in that method. So code after the t-c-f might not be executed, but the finally code is "guaranteed" (guaranteed in the sense of a non crashing immediately breaking non handleable error).

Sascha
  • 10,231
  • 4
  • 41
  • 65
2

Yes, there would be something very critically wrong.

And that is, your code would only run if there is an error.

Statements inside finally always run, regardless of an exception being thrown. That is the point.

Noon Silk
  • 54,084
  • 6
  • 88
  • 105
  • 2
    Cleanup code, for example, that you want to be run whether or not there's an error. That belongs in a finally block. – Michael Petrotta Oct 05 '10 at 07:15
  • You could make sure it errors every time by adding Throw new Exception(); as your last line in the Try block LOL – JumpingJezza Oct 05 '10 at 07:16
  • 2
    I think you misunderstood the "all the statements after catch block", to me it sounds like try { ...; } catch { ....; } *all the statements*; – Maxem Oct 05 '10 at 07:17
  • @JumpingJezza: Yes, but that statement is confused, because the code inside a finally isn't natively inside a try block, so an errors there need to be caught just as anywhere else. Your code inside a finally should be robust such that it actively goes out of its way to not generate exceptions. – Noon Silk Oct 05 '10 at 07:18
  • @Maxem: That is one interpretation, but I can't imagine the purpose of asking it, as it would be so bizar to be confused by that ... – Noon Silk Oct 05 '10 at 07:20
  • @Noon Silk: Jokes - definitely don't throw extra exceptions as they are resource expensive. – JumpingJezza Oct 05 '10 at 07:21
2

finally block especially used at the time of exception prevention. If any runtime error occurs, the program may lead to terminate. So at this time, it will call finally block before going to terminate the program. Usually 'finally' contains connection closing statements, save operations and file input, output close operations.

janasainik
  • 811
  • 5
  • 20
  • 40
1

If your code never throws exception, or you are consuming all exception that will be correct. That is not what always happens.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186
0

The question was indeed answered here (how to use finally)

My understanding of the answer is: there would be circumstances in which we would throw some exception that the except block won't be able to handle. What do you do in that situation? You wanna move on? Not a great idea! You better print something that indicates that you passed through a stage where an exception may or may not have occurred, if the exception occurred it should have been handled by the catch statement and if it was not handled, there may be some unmatched exception

Rajesh
  • 1
  • 1