try catch finally execution order conclusion
- Regardless of whether there is an exception or not, the code in the finally block will be executed;
- When there is a return in try and catch, finally will still execute;
- Finally is executed after the expression operation after return (the value after the operation is not returned at this time, but the value to be returned is saved first. No matter what the code in finally is, the returned value will not change, and it will still be the value saved before). Therefore, the return value of the function is determined before finally execution;
- It is best not to include return in finally, otherwise the program will exit in advance, and the return value is not the return value saved in try or catch.
Case 1
public class FinallyTest { public static void main(String[] args) { (new FinallyTest().test1()); } int test1(){ int x = 1; try { return ++x; }finally { ++x; } } }
2
Analysis: In the try statement, when executing the return statement, the result to be returned is ready. At this moment, the program goes to finally execute.
Before turning, try first store the result to be returned in a local variable different from x. After finally executing, take out the result from it, return it.
Therefore, even if the variable x is finally changed, the return result will not be affected.
Case 2
public class FinallyTest { public static void main(String[] args) { (new FinallyTest().test2()); } int test2(){ int i = 1; try{ i++; ("try block, i = "+i); }catch(Exception e){ i++; ("catch block i = "+i); }finally{ i = 10; ("finally block i = "+i); } return i; } }
try block, i = 2
finally block i = 10
10
That's right, it will be executed in order, first execute the code segment in the try, if there is no exception, it will be finally returned.
Case 3
public class FinallyTest { public static void main(String[] args) { (new FinallyTest().test3()); } int test3(){ int i = 1; try{ i++; ("try block, i = "+i); return i; }catch(Exception e){ i ++; ("catch block i = "+i); return i; }finally{ i = 10; ("finally block i = "+i); } } }
try block, i = 2
finally block i = 10
2
Analysis: The code is executed in sequence from try to finally. Since finally will be executed no matter what, the statements in try will not be returned directly. In the return block of a try statement, the reference variable returned by return is not the reference variable i defined outside the try statement, but the system redefines a local referencei
, this reference points to the referencei
The corresponding value is2
, even if quoted in finally statementi
Pointed to the value10
, because the reference returned by return is no longeri
, buti
, so the value of referenced i has nothing to do with the return value in the try statement.
Packaging Type
But, this is only part of it, ifi
Change to a reference type instead of a basic type, let’s see how the output is. The example is as follows:
public class FinallyTest { public static void main(String[] args) { (new FinallyTest().testWrap()); } List<Object> testWrap(){ List<Object> list = new ArrayList<>(); try{ ("try"); ("try block"); return list; }catch(Exception e){ ("catch"); ("catch block"); return list; }finally{ ("finally"); ("finally block "); } } }
try block
finally block
main test i = [try, finally]
As you can see, the operation on the list collection has finally taken effect, why is this? We know that the basic types are stored in the stack, while for non-primitive types, they are stored in the heap, and the address in the heap is returned, so the content is changed.
Case 4
Now let's add a return to finally and see where the statement returns from.
public class FinallyTest { public static void main(String[] args) { (new FinallyTest().test3()); } int test3(){ int i = 1; try{ i++; ("try block, i = "+i); return i; }catch(Exception e){ i ++; ("catch block i = "+i); return i; }finally{ i = 10; ("finally block i = "+i); return i; //HERE } } }
try block, i = 2
finally block i = 10
10
As you can see, it is returned from the finally statement block. It can be seen that the JVM ignores the return statement in the try. However, there will be a yellow warning prompt for the return added in finally. Why is this?
Case 5
Adding a line of code to execute exceptions, as follows:
public class FinallyTest { public static void main(String[] args) { (new FinallyTest().test3()); } int test3(){ int i = 1; try{ i++; int m = i / 0; // HERE ("try block, i = "+i); return i; }catch(Exception e){ i ++; ("catch block i = "+i); return i; }finally{ i = 10; ("finally block i = "+i); return i; } } }
catch block i = 3
finally block i = 10
10
It can be seen that because there is finally a return statement, the exceptions in try and catch are digested, blocking the occurrence of exceptions, which is contrary to the original intention of using try and catch in the early stage, so the compiler will also prompt a warning.
Case 6
So if an exception occurs in finally, what impact will it have on the exceptions in try and catch?
public class FinallyTest { public static void main(String[] args) { (new FinallyTest().test3()); } int test3(){ int i = 1; try{ i++; ("try block, i = "+i); return i; }catch(Exception e){ i ++; ("catch block i = "+i); return i; }finally{ i = 10; int m = i / 0; // HERE ("finally block i = "+i); return i; } } }
try block, i = 2
Exception in thread "main" : / by zero
at .test3(:21)
at (:6)
This prompt indicates the exception information in finally, that is, once an exception occurs in finally, the exception information in try and catch will be digested and the purpose of exception information processing cannot be achieved.
Summarize
Summarize the above tests:
- Finally statements will always be executed
- If there is a return statement in try and catch and there is no return in finally, then modifying data other than the wrapping type, static variables and global variables in finally will not have any impact on the variables returned in try and catch (wrap type, static variables will change, global variables)
- Try not to use return statements in finally. If used, the return statements in try and catch will be ignored, and exceptions in try and catch will be ignored, blocking the occurrence of errors.
- Finally avoid throwing exceptions again. Once an exception occurs in finally, the code execution will throw exception information in finally, and the exceptions in try and catch will be ignored
Therefore, in actual projects, finally is often used to close streams or database resources, and does not do other operations.
The above is personal experience. I hope you can give you a reference and I hope you can support me more.