img src: bing image
First, something to think about... :
- When does
finally
in Java codes be executed? - Do codes after
finally
get executed at all? - Does
finally
intry-catch-finally
block 100% gets executed? - If there is
return
mixed up withfinally
, what is the order of execution?
Second, a few things to keep in mind... :
-
There is good chance exceptions will occur in
try
block. One or more exceptions will be throw out. So, there can be multiplecatch
aftertry
block. -
If exceptions are isolated, then
catch
s can be arranged in whatever order you deem fit. But should there be inheritance hierarchy between those exceptions, you will need to put children exceptions before parent exceptions. This aims to let child exception gets caught by childcatch
instead of parents'catch
. So that specific exception's info can be output rather than a general parents' exception prompt. -
Generally, if exception did not occur in
try
block, thencatch
do not get to be excuted. But regardless of exceptions intry
block, should there be afinally
, thenfinally
gets executed.
Note: This is under general circumstance. I will come back to this later, and talk about other scenarios. -
Codes after
finally
get executed or not depend on whether there isretuen
intry
orcatch
.
In this blog, I will focus on these topics:
- When do codes after
finally
in Java execute? - When does
finally
in Java codes be executed? Or doesn't be executed? finally
is executed before or afterreturn
?- If there is also
return
infinally
, then should it just return? Willretuen
intry
return? - If there is no
return
infinally
but intry
, then how willretuen
intry
return? In what order? - If
finally
do not havereturn
in it but altered the variable to return. Then how willretuen
intry
return? Altered or unaltered?
img src: bing image
Now, let's dive right in... :
1. When do codes after finally
in Java execute?
See codes below:
public class TestFinally {
public static void main(String[] args){
try{
return;
}
finally{
System.out.println("Finally");
}
}
}
Program Output:
Finally
conclusion1: No exception occured,
finally
still gets executed.
If we replace return
to a normal output code:
public class TestFinally {
public static void main(String[] args){
try{
int a=3;
a+=5;
System.out.println(a);
}
finally{
System.out.println("Finally");
}
int b=5;
b+=5;
System.out.println(b);
}
}
Program Output:
8
Finally
10
conclusion2: Codes after
finally
will be executed.
Adding return
in try
won't be compiled because compiler found out this part of codes:
int b=5;
b+=5;
System.out.println(b);
are unreachable code
.
Some extra examples, example set 1:
public class TestFinally {
public static void a() throws Exception{
try{
throw new Exception();
}
catch(Exception e){
System.out.println("exception000");
}
finally{
System.out.println("finally111");
}
}
public static void main(String[] args){
try{
a();
}
catch(Exception e){
System.out.println("exception");
}
System.out.println("finished");
}
}
Program Output:
exception000
finally111
finished
Exception was caught in a()
, catch
in main
will not be executed. Codes after catch
will be executed.
If we commented catch
in a()
:
public class TestFinally {
public static void a() throws Exception{
try{
throw new Exception();
}
/*catch(Exception e){
System.out.println("exception000");
}*/
finally{
System.out.println("finally111");
}
}
public static void main(String[] args){
try{
a();
}
catch(Exception e){
System.out.println("exception");
}
System.out.println("finished");
}
}
Program Output:
finally111
exception
finished
Exception did not get caught in a()
, but was caught at catch
in main
. Codes after catch
will be executed.
If we commented finally
in a()
instead:
img src: bing image
package trycatchfinally;
public class TestFinally {
public static void a() throws Exception{
try{
throw new Exception();
}
catch(Exception e){
System.out.println("exception000");
}
/*finally{
System.out.println("finally111");
}*/
}
public static void main(String[] args){
try{
a();
}
catch(Exception e){
System.out.println("exception");
}
System.out.println("finished");
}
}
Program Output:
exception000
finished
Exception was caught in a()
, codes after catch
in main
will be executed.
example set 2:
public class TestFinally {
public static String output="";
public static void a(int i){
try{
if(i==1){
throw new Exception();
}
output+="1";
}
catch(Exception e){
output+="2";
return;
}
finally{output+="3";}
output+="4";
}
public static void main(String[] args){
a(0);
a(1);
System.out.println(TestFinally.output);
}
}
Program Output:
13423
If we remove return
phrase... :
package trycatchfinally;
public class TestFinally {
public static String output="";
public static void a(int i){
try{
if(i==1){
throw new Exception();
}
output+="1";
}
catch(Exception e){
output+="2";
//return;
}
finally{output+="3";}
output+="4";
}
public static void main(String[] args){
a(0);
a(1);
System.out.println(TestFinally.output);
}
}
Program Output:
1234234
conclusion3: If there is
return
intry
, codes afterfinally
will not be executed. Same thing goes forcatch
.
2. When does finally
in Java codes be executed? Or doesn't be executed?
- Case 1: Never reached
try
block, just skipped. Thenfinally
will not be executed. Which also indicates the necessary but not sufficient condition forfinally
be executed istry
block must be reachable, not skipped. - Case 2: There is something like
System.exit(0);
intry
block,System.exit(0);
shuts down JVM, which meansfinally
will 100% not be executed. - Case 3: JVM crashed first or get killed first.
- Case 4: there is an infinite loop (or some other non-interruptable, non-terminating statement) in the
try
block.
Now that we know codes after finally
get executed or not depend on whether there is retuen
in try
or catch
, it's time to think deeper...
3. finally
is executed before or after return
?
One statement I agree on:
finally
in Java codes is executed afterreturn
, but beforereturn
returns value.
See codes below:
public class TestFinally {
public static void main(String[] args) {
System.out.println(test1());
}
public static int test1() {
int b = 20;
try {
System.out.println("try");
return b += 80;
}
catch (Exception e) {
System.out.println("catch");
}
finally {
System.out.println("finally");
if (b > 25) {
System.out.println("b>25, b = " + b);
}
}
return b;
}
}
Program Output:
try
finally
b>25, b = 100
100
return
is executed first, but beforereturn
returns value,finally
is executed. Thenreturn
returns value.
public class TestFinally {
public static void main(String[] args) {
System.out.println(test11());
}
public static String test11() {
try {
System.out.println("try");
return test12();
} finally {
System.out.println("finally");
}
}
public static String test12() {
System.out.println("return statement");
return "after return";
}
}
Program Output:
try
return statement
finally
after return
4. If there is also return
in finally
, then should it just return? Will retuen
in try
return?
See codes below:
public class TestFinally {
public static void main(String[] args) {
System.out.println(test2());
}
public static int test2() {
int b = 20;
try {
System.out.println("try");
return b += 80;
} catch (Exception e) {
System.out.println("catch");
} finally {
System.out.println("finally");
if (b > 25) {
System.out.println("b>25, b = " + b);
}
return 200;
}
// return b;
}
}
Program Output:
try
finally
b>25, b = 100
200
conclusion:
return
infinally
will return, regardless ofreturn
intry
. Meaning it will overridereturn
intry
.
Also, once there isreturn
infinally
,return b;
outside becomes unreachable. It will need to be commented out.is executed. Thenreturn
returns value.
5. If there is no return
in finally
but in try
, then how will retuen
in try
return?
try{
return {expression A};
}finally{
do some work;
}
We now know that
finally
block generally gets executed. But in what order?
- execute {expression A}, push result into top of operand stack. (Some say copy to top of operand stack.)
- copy the top of operand stack (result of {expression A}) to local variable table.
- execute
finally
.- push value in local variable table in step 2 back to operand stack. (Some say copy it to top of operand stack, not exactly push.)
- return value at the top of operand stack.
conclusion: After step 1, value to return is already set. In order to execute finally
,
JVM will temporarily move the return value to local variable table, to free up operand stack for finally
.
And when finally
is complete, JVM will return the value to top of operand stack.
So no matter what finally
do (except returning a static value like return 200;
),
value to return will not be affected.
finally
is designed for clean up, not alter return value.
6. If finally
do not have return
in it but altered the variable to return.
Then how will retuen
in try
return? Altered or unaltered?
See codes below:
public class TestFinally {
public static void main(String[] args) {
System.out.println(test3());
}
public static int test3() {
int b = 20;
try {
System.out.println("try");
return b += 80;
} catch (Exception e) {
System.out.println("catch");
} finally {
System.out.println("finally");
if (b > 25) {
System.out.println("b>25, b = " + b);
}
b = 150;
}
return 2000;
}
}
Program Output:
try
finally
b>25, b = 100
100
conclusion: return did not changed to 150
, so if finally
try to alter a basic data types variables like an int
or double
, affects would not take place.
But if it tries to alter a wrapper class like Interger
, or some normal object like Map map = new HashMap();
, affects would take place.
reference:
[1] https://stackoverflow.com/questions/65035/does-finally-always-execute-in-java