Considering this code, can I be absolutely sure that the finally block always executes, no matter what something() is?
try {
something();
return success;
}
catch (Exception e) {
return failure;
}
finally {
System.out.println("I don't know if this will get printed out");
}
Yes, finally will be called after the execution of the try or catch code blocks.
The only times finally won't be called are:
If you invoke System.exit()
If you invoke Runtime.getRuntime().halt(exitStatus)
If the JVM crashes first
If the JVM reaches an infinite loop (or some other non-interruptable, non-terminating statement) in the try or catch block
If the OS forcibly terminates the JVM process; e.g., kill -9 <pid> on UNIX
If the host system dies; e.g., power failure, hardware error, OS panic, et cetera
If the finally block is going to be executed by a daemon thread and all other non-daemon threads exit before finally is called
Example code:
public static void main(String[] args) {
System.out.println(Test.test());
}
public static int test() {
try {
return 0;
}
finally {
System.out.println("something is printed");
}
}
Output:
something is printed.
0
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.
Here's the official words from the Java Language Specification.
14.20.2. Execution of try-finally and 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.
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();
}
}
Here's an elaboration of Kevin's answer. It's important to know that the expression to be returned is evaluated before finally, even if it is returned after.
public static void main(String[] args) {
System.out.println(Test.test());
}
public static int printX() {
System.out.println("X");
return 0;
}
public static int test() {
try {
return printX();
}
finally {
System.out.println("finally trumps return... sort of");
return 42;
}
}
Output:
X
finally trumps return... sort of
42
I tried the above example with slight modification-
public static void main(final String[] args) {
System.out.println(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 System.out out is executed.
After executing the finally block the try block returns 2, rather than returning 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 System.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.
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).
A logical way to think about this is:
Code placed in a finally block must be executed whatever occurs within the try block
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
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.
The only exception to this is if the VM shuts down completely during the try block e.g. by 'System.exit'
finally is always executed unless there is abnormal program termination (like calling System.exit(0)..). so, your sysout will get printed
No, not always one exception case is//
System.exit(0);
before the finally block prevents finally to be executed.
class A {
public static void main(String args[]){
DataInputStream cin = new DataInputStream(System.in);
try{
int i=Integer.parseInt(cin.readLine());
}catch(ArithmeticException e){
}catch(Exception e){
System.exit(0);//Program terminates before executing finally block
}finally{
System.out.println("Won't be executed");
System.out.println("No error");
}
}
}
Also a return in finally will throw away any exception. http://jamesjava.blogspot.com/2006/03/dont-return-in-finally-clause.html
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 finally 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.
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.
NOT ALWAYS
The Java Language specification describes how try-catch-finally and try-catch blocks work at 14.20.2
In no place it specifies that the finally block is always executed.
But for all cases in which the try-catch-finally and try-finally blocks complete it does specify that before completion finally must be executed.
try {
CODE inside the try block
}
finally {
FIN code inside finally block
}
NEXT code executed after the try-finally block (may be in a different method).
The JLS does not guarantee that FIN is executed after CODE.
The JLS guarantees that if CODE and NEXT are executed then FIN will always be executed after CODE and before NEXT.
Why doesn't the JLS guarantee that the finally block is always executed after the try block? Because it is impossible. It is unlikely but possible that the JVM will be aborted (kill, crash, power off) just after completing the try block but before execution of the finally block. There is nothing the JLS can do to avoid this.
Thus, any software which for their proper behaviour depends on finally blocks always being executed after their try blocks complete are bugged.
return instructions in the try block are irrelevant to this issue. If execution reaches code after the try-catch-finally it is guaranteed that the finally block will have been executed before, with or without return instructions inside the try block.
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.
Because a finally block will always be called unless you call System.exit() (or the thread crashes).
Concisely, in the official Java Documentation (Click here), it is written that -
If the JVM exits while the try or catch code is being executed, then
the finally block may not execute. Likewise, if the thread executing
the try or catch code is interrupted or killed, the finally block may
not execute even though the application as a whole continues.
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;
}
}
Answer is simple YES.
INPUT:
try{
int divideByZeroException = 5 / 0;
} catch (Exception e){
System.out.println("catch");
return; // also tried with break; in switch-case, got same output
} finally {
System.out.println("finally");
}
OUTPUT:
catch
finally
finally block is always executed and before returning x's (calculated) value.
System.out.println("x value from foo() = " + foo());
...
int foo() {
int x = 2;
try {
return x++;
} finally {
System.out.println("x value in finally = " + x);
}
}
Output:
x value in finally = 3
x value from foo() = 2
Yes, it will. No matter what happens in your try or catch block unless otherwise System.exit() called or JVM crashed. if there is any return statement in the block(s),finally will be executed prior to that return statement.
Adding to #vibhash's answer as no other answer explains what happens in the case of a mutable object like the one below.
public static void main(String[] args) {
System.out.println(test().toString());
}
public static StringBuffer test() {
StringBuffer s = new StringBuffer();
try {
s.append("sb");
return s;
} finally {
s.append("updated ");
}
}
Will output
sbupdated
Yes It will.
Only case it will not is JVM exits or crashes
Yes, finally block is always execute. Most of developer use this block the closing the database connection, resultset object, statement object and also uses into the java hibernate to rollback the transaction.
finally will execute and that is for sure.
finally will not execute in below cases:
case 1 :
When you are executing System.exit().
case 2 :
When your JVM / Thread crashes.
case 3 :
When your execution is stopped in between manually.
I tried this,
It is single threaded.
public static void main(String args[]) throws Exception {
Object obj = new Object();
try {
synchronized (obj) {
obj.wait();
System.out.println("after wait()");
}
} catch (Exception ignored) {
} finally {
System.out.println("finally");
}
}
The main Thread will be on wait state forever, hence finally will never be called,
so console output will not print String: after wait() or finally
Agreed with #Stephen C, the above example is one of the 3rd case mention here:
Adding some more such infinite loop possibilities in following code:
// import java.util.concurrent.Semaphore;
public static void main(String[] args) {
try {
// Thread.sleep(Long.MAX_VALUE);
// Thread.currentThread().join();
// new Semaphore(0).acquire();
// while (true){}
System.out.println("after sleep join semaphore exit infinite while loop");
} catch (Exception ignored) {
} finally {
System.out.println("finally");
}
}
Case 2: If the JVM crashes first
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public static void main(String args[]) {
try {
unsafeMethod();
//Runtime.getRuntime().halt(123);
System.out.println("After Jvm Crash!");
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
private static void unsafeMethod() throws NoSuchFieldException, IllegalAccessException {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
unsafe.putAddress(0, 0);
}
Ref: How do you crash a JVM?
Case 6: If finally block is going to be executed by daemon Thread and all other non-daemon Threads exit before finally is called.
public static void main(String args[]) {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
printThreads("Daemon Thread printing");
// just to ensure this thread will live longer than main thread
Thread.sleep(10000);
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
};
Thread daemonThread = new Thread(runnable);
daemonThread.setDaemon(Boolean.TRUE);
daemonThread.setName("My Daemon Thread");
daemonThread.start();
printThreads("main Thread Printing");
}
private static synchronized void printThreads(String str) {
System.out.println(str);
int threadCount = 0;
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread t : threadSet) {
if (t.getThreadGroup() == Thread.currentThread().getThreadGroup()) {
System.out.println("Thread :" + t + ":" + "state:" + t.getState());
++threadCount;
}
}
System.out.println("Thread count started by Main thread:" + threadCount);
System.out.println("-------------------------------------------------");
}
output: This does not print "finally" which implies "Finally block" in "daemon thread" did not execute
main Thread Printing
Thread :Thread[My Daemon Thread,5,main]:state:BLOCKED
Thread :Thread[main,5,main]:state:RUNNABLE
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE
Thread count started by Main thread:3
-------------------------------------------------
Daemon Thread printing
Thread :Thread[My Daemon Thread,5,main]:state:RUNNABLE
Thread :Thread[Monitor Ctrl-Break,5,main]:state:RUNNABLE
Thread count started by Main thread:2
-------------------------------------------------
Process finished with exit code 0
Consider the following program:
public class SomeTest {
private static StringBuilder sb = new StringBuilder();
public static void main(String args[]) {
System.out.println(someString());
System.out.println("---AGAIN---");
System.out.println(someString());
System.out.println("---PRINT THE RESULT---");
System.out.println(sb.toString());
}
private static String someString() {
try {
sb.append("-abc-");
return sb.toString();
} finally {
sb.append("xyz");
}
}
}
As of Java 1.8.162, the above code block gives the following output:
-abc-
---AGAIN---
-abc-xyz-abc-
---PRINT THE RESULT---
-abc-xyz-abc-xyz
this means that using finally to free up objects is a good practice like the following code:
private static String someString() {
StringBuilder sb = new StringBuilder();
try {
sb.append("abc");
return sb.toString();
} finally {
sb = null; // Just an example, but you can close streams or DB connections this way.
}
}
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.
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.
Related
Here's an example from the book "Java All-in-one desk reference"
public class CrazyWithZeros {
public static void main(String[] args) {
try {
int answer = divideTheseNumbers(5, 0);
} catch (Exception e) {
System.out.println("Tried twice, still didn't work!");
}
}
public static int divideTheseNumbers(int a, int b) throws Exception {
int c;
try {
c = a / b;
System.out.println("It worked!");
} catch (Exception e) {
System.out.println("Didn't work the first time.");
c = a / b;
System.out.println("It worked the second time!");
} finally {
System.out.println("Better clean up my mess.");
}
System.out.println("It worked after all.");
return c;
}
}
After the finally clause executes, the ArithmeticException is thrown back up to the calling method. The statement System.out.println("It worked after all.");would never be executed in this case. But what happened to the return c;?
I wonder whether the return statement would still return the result of the division or not?
========
I tried to replace "System.out.println("Better clean up my mess.");" with "System.out.println(c);", then it's compiled and the results are as follows:
Didn't work the first time.
0
Tried twice, still didn't work!
I can't believe the variable c could be calculated. (it's the wrong number, though) Why could this happen?
Then I also tried to replace "System.out.println("Better clean up my mess.");" with "return c;" and deleted the statements below the finally block, it's compiled again...Since the finally block is executed whether or not any exceptions are thrown by the try block or caught by any catch blocks, the return c; should be executed. But here're the results:
Didn't work the first time.
looks like c couldn't get returned...
return c is not executed either. It goes straight to the catch block in your main method.
What do you expect performing an error-prone operation the second time? :)
It is gonna generate an exception of the same type you came in the catch block with, but at that time it would not be handled - you don't have another try-catch within this catch block.
The finally is executed always regardless either an exception occurs or a normal process flow proceeds. In your case, you come to the finally block with the exception and throw it to the caller (main) where it gets handled by its own catch block.
I wonder whether the return statement would still return the result of the division or not?
What do you want to return? You haven't initialized the variable c and there is no correct record to this variable. Therefore, Java doesn't allow to write "something unexpected or unpredictable" into the c.
A method returns some value if it is executed without exception or error.
finally block does not have any impact on whether return statement will be executed or not. (of course, finally block should not throw any further exception)
catch block determines whether that exception should be propagated further or handled within the method.
In the given example, an ArithmeticException is thrown from try block and it will be handled by respective catch block. As catch blocks again throws the same exception, given return statement would never execute.
In short, return c; is never executed in above program and variable c will be deleted as any other local variable.
When I have a code like below, Compiler complains that "test() method must return a result of type int"
class ExecptionExample {
public static void main(String[] args) {
System.out.println("Result :"+test());
}
private static int test(){
try{
System.out.println("In try");
throw new StackOverflowError("SOError");
} catch(Exception e){
System.out.println("In catch");
//throw new ArrayIndexOutOfBoundsException();
} finally{
System.out.println("In finally");
//throw new RuntimeException();
}
System.out.println("Outside try-catch");
//return 0;
}
}
If I uncomment last line "return 0" then it compile and run but control never reaches at "return 0" and never prints "Outside try-catch"
Consider code below,
class ExecptionExample {
public static void main(String[] args) {
System.out.println("Result :"+test());
}
private static int test(){
try{
System.out.println("In try");
throw new StackOverflowError("SOError");
} catch(Exception e){
System.out.println("In catch");
//throw new ArrayIndexOutOfBoundsException();
} finally{
System.out.println("In finally");
throw new RuntimeException();
}
//System.out.println("Outside try-catch");
//return 0;
}
}
In above code, compiler doesn't complain about "return int value required".
So how things work? what is the rule that compiler checks for return required and not?
I am thinking as finally block is always going to be executed (leaving few conditions) and RuntimeException is thrown in finally, so compiler doesn't require return int value? Please confirm my understanding.
I am aware that StackOverflowError is not catch by Exception.
I just want to confirm one thing, in finally block it throws unchecked exception, is that the cause that compiler will not check return? because throwing unchecked exception from try block without finally block requires return and with finally block it doesn't requires return.
It is because finally you are throwing a RuntimeException which will always be thrown before returning anything from the function.
Now if you put return statement in try block. The Exception will still be thrown because finally block is executed just before returning data (but after executing return statement). But compiler will not give you any error.
But if you put a return statement after try-catch block compiler will give you an error. It is because try-catch block itself is throwing an exception and compiler will never reach the code written afterwards.
whatever finally block returns will be the final value of Method actually.
public static void main(String[] args) {
System.out.println("Result :"+test());
}
private static int test(){
try{
System.out.println("In try");
return 5;
} catch(Exception e){
System.out.println("In catch");
return 5;
} finally{
System.out.println("In finally");
return 10; //finally return will be the final Return
}
// System.out.println("Outside try-catch");
//return 0;
}
Output will be Printed as 10 . It means whatever finally block returns will be the final value of method test().
Now came to your Question.
Question 1 . Compiler complains that test() method must return a result of type int ?
Ans:- It is must to return type or sub-type Variable if you define a method with return type except void. In void there is no need to return any value.
Question 2 : I romove the comment from last line return 0 then it compile and run but control never reaches at "return 0" and never prints "Outside try-catch". Why ?
Ans:- this will compiles fine because one return value which is required is fulfilled by just removing your comments of line return 0.
but in your try block
throw new StackOverflowError("SOError"); // throwing an error which cannot be handled using Exception Handler in Catch Block
StackOverflowError is an error not an Exception . So, It will not catched in catch Block. So, After finally block your method will be terminated. Control will never go to this Statement.
System.out.println("Outside try-catch");
Question 3 : Why compiler doesn't complain about return int value required??
Ans:- finally block throwing an Exception which will be the final Exception statement will be executed and there is no catch block to handle this. So, Method test() will be terminated without taking care of any return value and delegate the Exception to the Caller Statement (which is main Here).
So, It will compiles fine but prone to an Exception.
Thank You.
Whenever you encounter an exception, the program breaks and displays the exception. It does not matter whether it reaches the return value or not. This is to prevent any unwanted conditions to be executed.
You can check for try-catch-finally blocks and how they are executed. There is a lot of information about it (http://tutorials.jenkov.com/java-exception-handling/basic-try-catch-finally.html).
As finally block will always executes in the first example, where you only do syso, the method does not end that is why return is required. In the second one you throw runtime, which ends the method execution.
public class CheckProg {
public int math(int i) {
try {
int result = i / 0;
// throw new IOException("in here");
} catch (Exception e) {
return 10;
} finally {
return 11;
}
}
public static void main(String[] args) {
CheckProg c1 = new CheckProg();
int res = c1.math(10);
System.out.println("Output :" + res);
}
Question: If I run the above code, I get the result as Output: 11
Why? Shouldn't the exception be caught before in the catch block and returned?
Shouldn't the exception be caught before in the catch block and returned ?
It is being caught, and that return statement is being executed... but then the return value is being effectively replaced by the return statement in the finally block, which will execute whether or not there was an exception.
See JLS 14.20.2 for details of all the possibilities. In your case, this is the path:
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:
If the run-time type of V is assignment compatible with a catchable exception class of any catch clause of the try statement, then the first (leftmost) such catch clause is selected. The value V is assigned to the parameter of the selected catch clause, and the Block of that catch clause is executed. Then there is a choice:
If the catch block completes normally [ ... ignored, because it doesn't ]
If the catch block completes abruptly for reason R, then the finally block is executed. Then there is a choice:
If the finally block completes normally [ ... ignored, because it doesn't ]
If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).
So that bottom line is the important one - the "reason S" (in our case, returning the value 11) ends up being the way that the try statement completes abruptly.
Yes. But the finally block is always executed afterwards and overrules the return value!
Finally block gets executed whether or not an exception occurs.
It is pretty much self-explanatory. Catch block is executing because there is an exception. Finally will execute as its execution is guaranteed irrespective of an exception.
Note - If you have given some other statement(s) instead of return, both statements have been executed. but in case of return, only last return is being executed.
} catch (Exception e) {
System.out.println("10");
} finally {
System.out.println("11");
}
The "finally" keyword is used to create a block of code that follows a try block. A finally block of code always executes, whether or not an exception has occurred.
try
{
final int x=100;
System.out.println("The value of x is"+ x);
}
catch(Exception e)
{
System.out.println(e);
}
finally
{
System.out.println("Finally Block executed");
}
Is there any functional difference?
Connection c = null;
try {
c = getConnection();
c.doStuff();
} finally {
if (c!=null) c.close();
}
vs
Connection c = null;
c = getConnection();
c.doStuff();
try {
} finally {
if (c!=null) c.close();
}
vs
Connection c = null;
try {
c = getConnection();
} finally {
if (c!=null) c.close();
}
c.doStuff();
I feel that all of them will do the same thing in all cases
Craig already addressed the unhandled exception issue, but I wanted to make it clear. I coded up two examples (the last is just bad because you could be working with a broken connection after an exception has occurred, don't do that). Here is a simple example that throws an ArrayIndexOutOfBoundsException:
class TryCatchFinally {
static int [] array = new int[1];
public static void main(String [] args) throws Exception {
if (args[0].startsWith("1")) {
version1();
} else if (args[0].startsWith("2")) {
version2();
}
}
static int version1() {
int r = 0;
try {
System.out.println("In Try.");
return array[1];
} catch (Exception e) {
System.out.println("In Catch.");
} finally {
System.out.println("In Finally.");
}
System.out.println("In Return.");
return r;
}
static int version2() {
int r = array[1];
try {
System.out.println("In Try.");
} catch (Exception e) {
System.out.println("In Catch.");
} finally {
System.out.println("In Finally.");
}
System.out.println("In Return.");
return r;
}
}
And here is the execution:
(TryCatchFinally)$ javac *.java
(TryCatchFinally)$ java TryCatchFinally 1
In Try.
In Catch.
In Finally.
In Return.
(TryCatchFinally)$ java TryCatchFinally 2
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at TryCatchFinally.version2(TryCatchFinally.java:24)
at TryCatchFinally.main(TryCatchFinally.java:7)
(TryCatchFinally)$
As you can see in the first version an exception handler was registered because the exception occurred within the context of a try block. In the second version there was no registered exception handler and the default exception handler was invoked (meaning an uncaught exception).
An exception that occurs outside of a try-finally block is by definition an unhandled exception. That being the case, you don't have any guarantees about how the operating system or runtime will deal with it. Chances are good that an exception unwind won't be triggered, your code will simply abort (maybe abend describes it better in this discussion--"abnormal end"), and your finally block will never execute.
The point of try-finally is to guarantee that code cleanup occurs, and occurs in the correct context.
You must be thinking that the code in the finally block is always going to execute no matter what, and that it is going to execute after the entire method finishes, therefore it doesn't matter whether the other code is located inside or outside the try-finally construct, but that is not correct.
So if you want any run-time guarantees of correct behavior your first example is the only correct one.
In your first example, you acquire and more importantly use a connection (to a database, one would presume) inside the try block. If an exception occurs within the try block, then the finally block will execute and close your connection.
In your second example, your connection is acquired and used completely outside of the try-catch construct. If an exception occurs using the connection, it is likely that the whole context will just be tossed out, your finally block will not execute, and your connection will not be closed.
In your third example, finally is going to execute after try, but before any code that comes after the finally block. You will generate an exception trying to use the connection, because the connection has already been explicitly closed.
This question already has answers here:
Returning from a finally block in Java
(6 answers)
Multiple returns: Which one sets the final return value?
(7 answers)
Closed 9 years ago.
Can we use return statement in finally block. Can this cause any problem?
Returning from inside a finally block will cause exceptions to be lost.
A return statement inside a finally block will cause any exception that might be thrown in the try or catch block to be discarded.
According to the Java Language Specification:
If execution of the try block completes abruptly for any other reason
R, then the finally block is executed, and 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).
Note: As per JLS 14.17 - a return statement always completes abruptly.
Yes you can write the return statement in a finally block and it will override the other return value.
EDIT:
For example in below code
public class Test {
public static int test(int i) {
try {
if (i == 0)
throw new Exception();
return 0;
} catch (Exception e) {
return 1;
} finally {
return 2;
}
}
public static void main(String[] args) {
System.out.println(test(0));
System.out.println(test(1));
}
}
The output is always 2, as we are returning 2 from the finally block. Remember the finally always executes whether there is a exception or not. So when the finally block runs it will override the return value of others. Writing return statements in finally block is not required, in fact you should not write it.
Yes you can,But you should not 1 ,because the finally block is meant for a special purpose.
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.
Writing your logic inside it is not recommended.
You can write return statement in finally block but the value returned from try block will be updated on the stack and not the finally block return value.
Let us say you have this function
private Integer getnumber(){
Integer i = null;
try{
i = new Integer(5);
return i;
}catch(Exception e){return 0;}
finally{
i = new Integer(7);
System.out.println(i);
}
}
and you are calling this from main method
public static void main(String[] args){
System.out.println(getNumber());
}
This prints
7
5