Do you really need the 'finally' block

JavaException Handling

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

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.

Solution 3 - Java

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.

Solution 4 - Java

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.

Solution 5 - Java

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).

Solution 6 - Java

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.

Solution 7 - Java

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.

Solution 8 - Java

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

Solution 9 - Java

The question was indeed answered here (https://stackoverflow.com/questions/3354823/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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAmit Kumar GuptaView Question on Stackoverflow
Solution 1 - JavaAngelos MakrygiorgosView Answer on Stackoverflow
Solution 2 - JavaSisyphusView Answer on Stackoverflow
Solution 3 - JavawillcodejavaforfoodView Answer on Stackoverflow
Solution 4 - JavaMax LybbertView Answer on Stackoverflow
Solution 5 - JavaSaschaView Answer on Stackoverflow
Solution 6 - JavaNoon SilkView Answer on Stackoverflow
Solution 7 - JavajanasainikView Answer on Stackoverflow
Solution 8 - JavafastcodejavaView Answer on Stackoverflow
Solution 9 - JavaRajeshView Answer on Stackoverflow