Is finally executed if in try return?
try {
...
return qwe;
} catch {...}
finally {...}
Is finally
satisfied if try
has return
?
4 answers
Sure. That's what he finally does. However, the result may be a little puzzling.
import java.util.*;
import java.lang.*;
class Main
{
public static int test() {
try {
System.out.println("test");
return 1;
}
finally {
System.out.println("fin");
return 2;
}
//return 3;
}
public static void main (String[] args) throws java.lang.Exception
{
int i = test();
System.out.println("test return " + i);
}
}
The output will be as follows:
test
fin
test return 2
But the compiler will not allow you to uncomment the line with return 3;
.
Finlally executed almost always.
Update, I would like to complete my answer about exception handling in java. Let's consider 3 cases that seemed interesting to me. Here is the testFinally method()
static int testFinally() {
for (int i = 0; i < 10; i++) {
System.out.println("i = " + i);
try {
if (i == 3) {
throw new Exception();
}
} catch (Exception e) {
System.out.println("Exception!");
return i;
} finally {
System.out.println("Finally ");
}
}
return -1;
}
In this case, we can see that the finally block always works, which was required to prove.
The second case is related to multithreading, or rather to the fact that this rule is also true for multithreaded applications.
public static void main(String[] args) throws Exception {
Thread t = new Thread(new Runnable(){
public void run() {
try {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread() + ": " + i);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
System.out.println("Interrupted!");
} finally {
System.out.println("I'm in the finally block!");
}
}
});
t.start();
TimeUnit.SECONDS.sleep(5);
System.out.println("main() finished");
}
}
Here everything will also be correct, that is, the finally block will work. But not for the daemon threads. Oddly enough, Java will nail them down and not choke without executing fanali blocks.
public static void main(String[] args) throws Exception {
Thread t = new Thread(new Runnable(){
public void run() {
try {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread() + ": " + i);
TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
System.out.println("Interrupted!");
} finally {
System.out.println("I'm in the finally block!");
}
}
});
t.setDaemon(true);
t.start();
TimeUnit.SECONDS.sleep(5);
System.out.println("main() finished");
}
}
Which proves that there are exceptions everywhere, even in exceptions)
In addition to the existing answers, I provide links to the relevant sections of the documentation.
Why finally
should be called after return
is described in the Java language specification in the software chapters return
and finally
:
14.17. The return Statement
...
A return statement with an Expression attempts to transfer control to the invoker of the method or lambda body that contains it; the value of the Expression becomes the value of the method invocation. More precisely, execution of such a return statement first evaluates the Expression. If the evaluation of the Expression completes abruptly for some reason, then the return statement completes abruptly for that reason. If evaluation of the Expression completes normally, producing a value V, then the return statement completes abruptly, the reason being a return with value V.14.20.2. Execution of try-finally and try-catch-finally
...
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).
Translation:
14.17. Instructions
return
...
A return statement with an Expression statement attempts to pass control to the code that called the method or the lambda expression that contains the statement; the value of Expression becomes the value of the method call. More strictly speaking, executing such a return statement first evaluates Expression. If the Expression calculation terminates prematurely for some reason, the return statement terminates prematurely for the same reason. If the Expression calculation completes normally, by giving a value of V, the return statement terminates prematurely for the reason that it is a return of the value of V14.20.2. Executing
try-finally
andtry-catch-finally
...
If the execution of the try block ends prematurely for some other reason R, the finally block is executed. Further, the following options are possible.
- If the finally block terminates normally, the try statement terminates prematurely due to R.
- If the finally block terminates prematurely S, the try statement terminates prematurely due to reason S (reason R is ignored).
In short, calling return
is a special case of premature termination, with premature termination from finally
overriding and discarding any premature termination in the try
block.
If in the {[9] block]} an exception will be thrown that will not be caught by any of the catch
blocks (if there are any), then it will be discarded and forgotten when return
is called, or when throwing a new exception in finally
.
In addition to the previous answers, I will add, in my opinion, the most obvious one. Here, the second return
in the finally
block overlaps the first one.
Taken here: https://programming.guide/java/try-finally.html