views:

13397

answers:

20

If I have a try/catch block with returns inside it, will the finally block be called?

For example:

try {  
    something();  
    return success;  
    }  
catch (Exception e) {   
    return failure;  
    }  
finally {  
    System.out.println "i don't know if this will get printed out."  
    }

I know I can just type this in an see what happens (which is what I'm about to do, actually) but when I googled for answers nothing came up, so I figured I'd throw this up as a question.

Thanks!

+59  A: 

finally will be called.

The only time finally won't be called is if you call System.exit() or if the JVM crashes first.

jodonnell
Or if the thread is interrupted.
Murali VP
+2  A: 

finally is always executed unless there is abnormal program termination (like calling System.exit(0)..). so, you sysout will get printed

shyam
+1  A: 

Yes it will get called. That's the whole point of having a finally keyword. If jumping out of the try/catch block could just skip the finally block it was the same as putting the System.out.println outside the try/catch.

Mendelt
+41  A: 

//proof code

class Test
{
    public static void main(String args[]) 
    { 
     System.out.println(Test.test()); 
    }

    public static int test()
    {
     try {  
             return 0;  
     }  
     finally {  
         System.out.println("finally trumps return.");
     }
    }
}

output:

finally trumps return. 
0
Kevin
A: 

That's actually true in any language...finally will always execute before a return statement, no matter where that return is in the method body. If that wasn't the case, the finally block wouldn't have much meaning.

Scott Dorman
A: 

The finally block is always executed unless there is abnormal program termination, either resulting from a JVM crash or from a call to System.exit(0).

On top of that, any value returned from within the finnally block will override the value returned prior to execution of the finally block, so be careful of checking all exit points when using try finally.

+28  A: 

Also, although it's bad practice, if there is a return statement within the finally block, it will trump any other return from the regular block. That is, the following block would return false:

try { return true; } finally { return false; }

Same thing with throwing exceptions from the finally block.

MooBob42
This is a REALLY bad practice. See http://stackoverflow.com/questions/48088/returning-from-a-finally-block-in-java for more info about why it's bad.
John Meagher
Agreed. A return within finally{} ignores any exception thrown in try{}. Scary!
neu242
+5  A: 

Also a return in finally will throw away any exception. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html

James A. N. Stauffer
+13  A: 

A logical way to think about this is:

  1. Code placed in a finally block must be executed whatever occurs within the try block
  2. So if code in the try block tries to return a value or throw an exception the item is placed 'on the shelf' till the finally block can execute
  3. Because code in the finally block has (by definition) a high priority it can return or throw whatever it likes. In which case anything left 'on the shelf' is discarded.
  4. The only exception to this is if the VM shuts down completely during the try block e.g. by 'System.exit'
Garth Gilmour
Is this just "a logical way to think about it" or is it really how the finally block is intended to work according to the specifications ? A link to a Sun resource would be very interesting in here.
matias
A: 

In addition to the point about return in finally replacing a return in the try block, the same is true of an exception. A finally block that throws an exception will replace a return or exception thrown from within the try block.

Alex Miller
A: 

If we have following code

class Test {
public static void main(String args[]) { System.out.println(Test.test()); }

public static int test()
{
   int i=0;

    try {  
            return i;  
    }  
    finally {  
              i=12;
        System.out.println("finally trumps return.");
    }
}

}

It prints 0 as the value of i instead of 12.... can any body explain why it happens...?

Can you include the statement where you print the value of i?
Ryan Guest
Assuming you print it in the caller, it happens because when you call return, i's value is 0. It gets copied to the return value location in the current runtime stack frame at that point. If you put "return i" after the i=12, you'd get 12.
Scott Stanchfield
+7  A: 

I tried the above example with slight modification-

public static void main(String[] args) {

System.out.println(Test.test());

}

public static int test() {

int i = 0;
try {
  i=2;
  return i;
} finally {
  i = 12;
  System.out.println("finally trumps return.");
}

}

The above code outputs-

finally trumps return.

2

This is because when return i; is executed i has a value 2. After this the finally block is executed where 12 is assigned to i and then sys out is executed.

After executing finally block the try block returns 2, rather than returning i=12, because this return statement is not executed again.

If you will debug this code in Eclipse then you'll get a feeling that after executing Sys out of finally block the return statement of try block is executed again. But this is not the case. It simply returns the value 2.

vibhash
+2  A: 

Finally is always run that's the whole point, just because it appears in the code after the return doesn't mean that that's how it's implemented. The Java runtime has the responsibility to run this code when exiting the try block.

For example if you have the following:

int foo() { 
    try {
        return 42;
    }
    finally {
        System.out.println("done");
    }
}

The runtime will generate something like this:

int foo() {
    int ret = 42;
    System.out.println("done");
    return 42;
}

If an uncaught exception is thrown the finally block will run and the exception will continue propagating.

Motti
+3  A: 

Because a finally block will always be called unless you call System.exit() (or the thread crashes).

Jay Riggs
+21  A: 

That is the whole idea of a finally block. It lets you make sure you do cleanups that might otherwise be skipped because you return, among other things, of course.

Finally gets called regardless of what happens in the try block, unless you call System.exit(int) or the Java Virtual Machine kicks out for some other reason.

Chris Cooper
A: 

Because the final is always be called in whatever cases you have. You don't have exception, it is still called, catch exception, it is still called

vodkhang
+9  A: 

In addition to the other responses, it is important to point out that 'finally' has the right to override any exception/returned value by the try..catch block. For example, the following code returns 12:

public static int getMonthsInYear(){
    try{
        return 10;
    } finally {
        return 12;
    }
}

Similarly, the following method does not throw an exception:

public static int getMonthsInYear(){
    try{
        throw new RuntimeException();
    } finally {
        return 12;
    }
}

While the following method does throw it:

public static int getMonthsInYear(){
    try{
        return 12;          
    } finally {
        throw new RuntimeException();
    }
}
Eyal Schneider
It should be noted that the middle case is precisely the reason why having a return statement inside a finally block is absolutely horrible (it could hide any Throwable).
Dimitris Andreou
+1  A: 

Consider this in a normal course of execution (i.e without any Exception being thrown): if method is not 'void' then it always explicitly returns something, yet, finally always gets executed

Gala101
A: 

This is because you assigned the value of i as 12, but did not return the value of i to the function. The correct code is as follows:

public static int test()
{
    int i=0;

    try {  
        return i;  
    }  
    finally {  
        i=12;
        System.out.println("finally trumps return.");
        return i;
    }
}
Wasim
+6  A: 

Here's the official words from the Java Language Specification.

JLS 14.20.2 Execution of try-catch-finally

A try statement with a finally block is executed by first executing the try block. Then there is a choice:

  • If execution of the try block completes normally, [...]
  • If execution of the try block completes abruptly because of a throw of a value V, [...]
  • If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice:
    • If the finally block completes normally, then the try statement completes abruptly for reason R.
    • If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).

The specification for return actually makes this explicit:

JLS 14.17 The return Statement

ReturnStatement:
     return Expression(opt) ;

A return statement with no Expression attempts to transfer control to the invoker of the method or constructor that contains it.

A return statement with an Expression attempts to transfer control to the invoker of the method that contains it; the value of the Expression becomes the value of the method invocation.

The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are any try statements within the method or constructor whose try blocks contain the return statement, then any finally clauses of those try statements will be executed, in order, innermost to outermost, before control is transferred to the invoker of the method or constructor. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a return statement.

polygenelubricants
This is exactly the answer I was looking for.
matias