77

Please see the following code and explain the output behavior.

public class MyFinalTest {

    public int doMethod(){
        try{
            throw new Exception();
        }
        catch(Exception ex){
            return 5;
        }
        finally{
            return 10;
        }
    }

    public static void main(String[] args) {

        MyFinalTest testEx = new MyFinalTest();
        int rVal = testEx.doMethod();
        System.out.println("The return Val : "+rVal);
    }

}

The result is the return Val : 10.

Eclipse shows a warning: finally block does not complete normally.

What happens to the return statement in catch block ?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Ammu
  • 5,067
  • 9
  • 34
  • 34
  • possible duplicate of [Why does changing the returned variable in a finally block not change the return value?](http://stackoverflow.com/questions/16030858/why-does-changing-the-returned-variable-in-a-finally-block-not-change-the-return) – fglez Apr 30 '13 at 07:32
  • 6
    A very popular interview question. – giannis christofakis Jun 29 '14 at 20:09

8 Answers8

82

It is overridden by the one in finally, because finally is executed after everything else.

That's why, a rule of thumb - never return from finally. Eclipse, for example, shows a warnings for that snippet: "finally block does not complete normally"

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
57

finally is always executed (the only exception is System.exit()). You can think of this behavior this way:

  1. An exception is thrown
  2. Exception is caught and return value is set to 5
  3. Finally block gets executed and return value is set to 10
  4. The function returns
assylias
  • 321,522
  • 82
  • 660
  • 783
Vladimir Ivanov
  • 42,730
  • 18
  • 77
  • 103
  • General rules of try/catch block: 1) Never return a value in the finally block. 2) Avoid throwing an exception in a finally or catch black, as it obscures the original exception. – Matt Aug 08 '12 at 04:36
  • 18
    Saying finally is always executed is a very dangerous thing. You really can't rely on it being executed for mission critical operations. Consider something like a power outage, a jvm corruption/crash, etc. I know it sounds a little nit-picky, but always is a strong word, and I think sometimes we forget that we live in the real world where disasters like that do occur. – corsiKa Feb 15 '13 at 18:26
20

This is an easy question if you remember the low level layout of the VM.

  1. The return value is put up the stack by the catch code.
  2. Afterwards, the finally code is executed and overwrites the value on the stack.
  3. Then, the method returns with the most up to date value (10) to be used by the caller.

If unsure about things like this, fall back to your understanding of the underlying system (ultimately going to assembler level).

(funny sidenote)

mafu
  • 31,798
  • 42
  • 154
  • 247
5

enter image description here

Finally block always get executed unless and until System.exit() statement is first in finally block.

So here in above example Exection is thrown by try statement and gets catch in catch block. There is return statement with value 5 so in stack call value 5 gets added later on finally block executed and latest return value gets added on top of the stack while returning value, stack return latest value as per stack behavior "LAST IN FIRST OUT" so It will return value as 10.

Avinash Pande
  • 1,510
  • 19
  • 17
3

The finally block is always executed (if the matching try was executed) so before the method returns 5 as in the catch block, it executes the finally block and returns 10.

MByD
  • 135,866
  • 28
  • 264
  • 277
2

In a nut shell, we could say finally block dominates return statement, irrespective of, if return present in try or catch block.

Always finally dominates in that use case.

public static int m1() {
    try {
        return 100;
    } 
    catch(Exception e)
    {
        return 101;
    }
    finally {
        return 102;
    }
}

Output - 102

Kms
  • 1,082
  • 2
  • 11
  • 27
1

finally block will always execute (only exception is it encounters System.exit() anywhere before it), so simply the 5 is replaced (overridden) by 10 before returning by finally block

irfan
  • 878
  • 9
  • 10
0

the finally section will execute always execute. e.g. if you have any thing to release, or log out sort of thing, if error occur then go to catch section else finally will execute.

Session session //  opened some session 
try 
{
 // some error 
}
catch { log.error }
finally 
{ session.logout();}

it should not used to return anything. you can use outside of.