35

I'm not familiar with java and I've been recently looking at some code written by some colleagues that's baffling me. Here's the gist of it:

public response newStuff(//random data inside) {
    try {
       response or = //gives it a value
       log.info(or.toString());
       return or;
    }
    catch ( Exception e) {
        e.printStackTrace();
    }
    finally {
        return null;
    }
}

Is there really any point in adding a finally block here? Couldn't I just add the return null inside the catch block, which would execute the same behavior, or am I wrong?

Flow
  • 23,572
  • 15
  • 99
  • 156
user1413969
  • 1,261
  • 2
  • 13
  • 25
  • 39
    Oh, don't put `return` statements in `finally` blocks. Please. – Sotirios Delimanolis Oct 21 '13 at 15:25
  • @SotiriosDelimanolis I've never seen or even thought about doing this. Wouldn't after calling return, you jump into the finally block again? – Cruncher Oct 21 '13 at 15:26
  • 9
    Your code will always return `null`. Putting `return` in `catch` is not the same thing as putting it in `finally`. – Rohit Jain Oct 21 '13 at 15:27
  • Go read this - http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html – OldProgrammer Oct 21 '13 at 15:27
  • @RohitJain I was thinking this at first too, however his `try` block ends with `return or;`, so the `finally` block would never execute unless he enters a `catch` block, right? – nhgrif Oct 21 '13 at 15:27
  • 3
    @nhgrif finally always executes, whether you catch an expection or not. The method cannot return without first going through finally. – Cruncher Oct 21 '13 at 15:28
  • @nhgrif Actually, the new return value in finally block will overwrite the existing return value. – Rohit Jain Oct 21 '13 at 15:28
  • Hmm. Okay, good to know. I'm not a `try-catch-finally` master by any measure. – nhgrif Oct 21 '13 at 15:29
  • *finally* blocks **always** execute, there's no point using a return there as the method will always return the same thing. – Jose-Rdz Oct 21 '13 at 15:34
  • 14
    It is strange to me that the designers of Java, JavaScript, Python, etc, all allowed a return inside a finally. It seems to add no additional power to the language while simultaneously inserting a terrible "gotcha" situation. The equivalent code would be illegal in C#. – Eric Lippert Oct 21 '13 at 21:33
  • @EricLippert I didn't even know that also Python had this! However I have **never** seen it used, and not even *mentioned* anywhere, while I *did* see it used in few Java programs. – Bakuriu Oct 22 '13 at 06:57
  • @AngelRodríguez you can have logic in a finally - it needn't always return the same thing - granted the example above does. – Phil Oct 22 '13 at 08:06
  • 2
    I read the title as Try/Catch (is) finally in Java. :D – Viktor Mellgren Oct 22 '13 at 08:35
  • Try/Catch/Finally are almost always a bad idea. Especially when you put a return somewhere inside it. – Fabinout Oct 22 '13 at 13:30
  • @Phil sure, i was just pointing to the sample code provided... bad English sorry... – Jose-Rdz Oct 22 '13 at 21:20
  • possible duplicate of [Returning from a finally block in Java](http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java) – Raedwald Oct 24 '13 at 07:20
  • See also http://stackoverflow.com/questions/421797/what-really-happens-in-a-try-return-x-finally-x-null-statement – Raedwald Oct 24 '13 at 07:23

10 Answers10

31

Is there really any point in adding a finally block here?

The answer to this is a resounding "no": putting a return statement in the finally block is a very bad idea.

I just add the return null inside the catch block, which would execute the same behavior, or am I wrong?

It wouldn't match the original behavior, but that's a good thing, because it would fix it. Rather than returning null unconditionally the way the original code does, the code with the return inside the catch block would return null only on errors. In other words, the value returned in the try branch would be returned to the caller unless there is an exception.

Moreover, if you add return null after the catch block, you would see the correct effect of returning null on exception. I would go even further, and put a single return in the method, like this:

response or = null;
try {
   or = //gives it a value
   log.info(or.toString());
} catch ( Exception e) {
    e.printStackTrace();
}
return or;
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 4
    Furthermore, I'd add that, `response` doesn't follow naming conventions. Also, I would highly advise against `catch(Exception e)` – Cruncher Oct 21 '13 at 15:33
  • 1
    Thanks. I'll make some changes to the code then. I didn't want to rush into making changes in case I was the local idiot. – user1413969 Oct 21 '13 at 15:53
  • Putting the `return` inside the catch block wouldn't yield the same behavior in case `e.printStackTrace()` would throw an exception. – Flow Oct 22 '13 at 07:49
  • @Flow does `e.printStackTrace()` ever throw anything (where `e` is non-null, as it would be here)? – Phil Oct 22 '13 at 08:10
  • `printStackTrace()` uses I/O, which could cause an exception. – Flow Oct 22 '13 at 09:22
  • @Flow in the case that `e.printStackTrace()` throws an exception, then you will not reach the return statement that is after the try...catch either. – Cruncher Oct 22 '13 at 12:45
  • Exactly, if you want to keep the semantic of the code presented in the question, i.e. never throw an `Exception` but return `null` instead, you have to put the `return or;` in the answer above in a `finally` block. I don't think that this answer is correct otherwise. – Flow Oct 22 '13 at 13:01
  • @Flow The OP does not want to mimic the semantic of the code that he posted - quite to the contrary, he is questioning its validity. – Sergey Kalinichenko Oct 22 '13 at 13:02
  • That is also correct. But op asked `I just add the return null inside the catch block, which would execute the same behavior, or am I wrong?` and you answered `You are absolutely right.` which is wrong. This [blalassadri answer](http://stackoverflow.com/a/19498813/194894) and even if the return in the finally would not override the return in the try block, it wouldn't yield the same semantic. – Flow Oct 22 '13 at 13:05
  • @Flow I edited the answer to explain how moving the `return` statement out of the `finally` block changes the semantic. Thanks! – Sergey Kalinichenko Oct 22 '13 at 13:23
  • @Cruncher I would also add that a variable named 'or' doesn't follow any naming convention system or scheme that I have ever encountered or can imagine. – user207421 Oct 24 '13 at 00:44
23

Actually, no. Finally is (nearly) always run, no matter what the result in the try-catch block; so this block always returns null. Here, look at this example:

public class Finally {

/**
 * @param args
 */
public static void main(String[] args) {
    System.out.println(finallyTester(true));
    System.out.println(finallyTester(false));
}

public static String finallyTester(boolean succeed) {
    try {
        if(succeed) {
            return "a";
        } else {
            throw new Exception("b");
        }
    } catch(Exception e) {
        return "b";
    } finally {
        return "c";
    }
  }

}

It will print "c" both times.

The above mentioned exception to the rule would be if the thread itself is interrupted; e.g. by System.exit(). This is however a rare thing to happen.

blalasaadri
  • 5,990
  • 5
  • 38
  • 58
  • 5
    +1 as it truly demonstrates what Netbeans warns of `return in finally block discards unhandled exceptions` – exexzian Oct 21 '13 at 16:52
5

The finally is always executed no matter what, and normally can be used to close sessions, etc. Don't put returns inside a finally block.

ranu
  • 622
  • 15
  • 25
X-Pippes
  • 1,170
  • 7
  • 25
4

This looks like a very bad practice. In this case your code will always return null.

The finally block is called last after the try-catch block runs. No matter if the try finished or the exception block was called. In this case, no matter which path of code is ran, you will always return null. In the "normal" case where you put the return null after the finally there's indeed a chance to return something (either from the try or from the catch block) and if no flow yields a return object, you fall back to the return null, but you don't always return null.

Avi
  • 21,182
  • 26
  • 82
  • 121
4

I've read that a lot of people simply answer "don't use return in a finally block", without any explanation. Well, actually the code you posted is a good example where a return in a finally block is causing massive confusion. Even the, as of time of writing this, most upvoted answer, got it wrong. Your code will always execute the return null; as last command, even if there is an Exception.

But I can think of a situation where a return in a finally block actually makes sense. It appears to me that the goal of the author of your code was that the method never throws a Throwable, but returns null instead. This can actually be achieved if you modify the code like this:

public Result newStuff() {
    Result res = null;
    try {
       res = someMethod();
       log.info(res.toString());
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    finally {
        return res;
    }
}

But note that this will not call printStackTrace() on Errors and Throwables which are not Exceptions.

Community
  • 1
  • 1
Flow
  • 23,572
  • 15
  • 99
  • 156
3

The "Finally" block will execute regardless of whether the "Catch" fires or not. So the behaviour is different than if you just put "return null" in the Catch block.

UpAllNight
  • 1,312
  • 3
  • 18
  • 30
3

There should be no return statement in the finally block,remove return.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
vinay Maneti
  • 1,447
  • 1
  • 23
  • 31
2

The need of finally block is where when you have such a code that should always be executed like you want to close your input stream or you want to close any connection etc.Just googled about this you will easily find the example for this.

In your case you are writing a method where you are returning something in try block and at the end you are writing finally block where you are returning null.I don't see any use of finally block here.

kailash gaur
  • 1,407
  • 3
  • 15
  • 28
1

Finally block is used if you want to execute some statements even if code in try block or catch block generates an exception or not. But as you are using return in try block then there is no significance of putting a return in finally block. You can return directly from catch block and can remove finally block.

Prateek
  • 342
  • 1
  • 3
  • 15
1

First understand why we need this three blocks in simple words for beginners.

1)try block: If you have doubt that your code will lead to an exception then put in try block

2)catch block: If exception arises then a piece of code you need to perform should be written in this block

3)finally block: If you want your piece of code to be executed no matters if exception arises or not then we go for finally block. Mainly this block is use for releasing resources. For example:

try{
   Connection conn=//something;
   //some code for database operations

}catch(SQLException e){
        e.printStackTrace()
}finally{
      conn=null;
}

No matter what is result, you have to make connection as null because it is heavy object which if referenced will create load on database as only few connection objects are available. Hence best way to keep them in finally block.

In your case, return null in finally block is bad approach as it will always return null although exception arises or not.

Shoaib Chikate
  • 8,665
  • 12
  • 47
  • 70