On the depth discrimination of finally statement block in Java

Source: Internet
Author: User
Tags finally block

Let's start by asking you a question: will the finally statement block be executed?

Many people think that the finally statement block is definitely going to be executed, including some very experienced Java programmers. Unfortunately, as most people think, the answer to this question is, of course, negative, so let's take a look at the following example.

Listing 1

public class Test {public      static void Main (string[] args) {          System.out.println ("Return value of Test ():" + Test ( ));      }         public static int Test () {          int i = 1;          if (i = = 1)          //return 0;         System.out.println ("the previous statement of Try Block");         i = i/0;           try {             System.out.println ("try block");               return i;         } finally {             System.out.println ("finally Block");}}}  


The results of Listing 1 are as follows:

The previous statement of Try block Exception in thread ' main ' java.lang.ArithmeticException:/by zero at Com.bj.charlie. Test.test (test.java:15) at Com.bj.charlie.Test.main (Test.java:6)


Also, if you remove the comment before the two statement that was commented in the previous example, the result is:

return value of Test (): 0

In both cases, the finally statement block is not executed, what is the problem?
The finally statement block executes only if the TRY statement block corresponding to finally is executed.
Both of these cases are returned before the TRY statement block (return) or throw an exception, so the finally statement block that the try corresponds to is not executed.


Well, will the finally statement block be executed even if the TRY statement block corresponding to finally is executed?
Take a look at the following example (Listing 2).


Listing 2

public class Test {public      static void Main (string[] args) {          System.out.println ("Return value of Test ():" + Test ( ));      }         public static int Test () {          int i = 1;             try {             System.out.println ("try block");             System.exit (0);               return i;         } finally {             System.out.println ("finally Block");}}}     


The results of Listing 2 are as follows:

Try Blocktry block

Finally statement block is still not executed, why?


Because we executed the System.exit (0) statement in the TRY statement block, the operation of the Java virtual machine was terminated.

It is said that the System.exit (0) method is essentially not invoked in a generic Java application.
Ok! No problem, we do not call System.exit (0) This method, then the finally statement block will certainly execute it?

The answer is still negative.

When a thread is interrupted (interrupted) or terminated (killed) when executing a try statement block or a catch statement block, the finally statement block corresponding to it may not be executed.
The more extreme situation is that when the thread runs a try statement block or a catch statement block, a sudden crash or a power outage, the finally statement block will definitely not be executed.
Some people may think that the reasons for the crash, power outages are not related, we just to illustrate the problem.

Finally Statement Example description

Let's look at a simple example (listing 3).

Listing 3.
public class Test {public     static void Main (string[] args) {         try {             System.out.println ("try block");               return;         } finally {             System.out.println ("finally Block");}}}    


The result of Listing 3 is:

Try block finally block

Listing 3 shows that the finally statement block is executed before the return statement in the TRY statement block


Let's look at another example.


Listing 4.

public class Test {public    static void Main (string[] args) {        System.out.println ("Reture Value of Test ():" + Test ());    }     public static int Test () {        int i = 1;         try {            System.out.println ("try block");            i = 1/0;              return 1;        } catch (Exception e) {            System.out.println ("Exception block");             return 2;        } finally {            System.out.println ("finally Block");}}}    


The result of Listing 4 is:

Try Blockexception block finally block reture value of test (): 2

Listing 4 illustrates that the finally statement block is executed before the return statement in the CATCH statement block.

From the above listing 3 and listing 4, we can see that

In fact, the finally statement block is executed before the return statement in a try or catch.
More generally, the finally statement block should be executed before the control transfer statement, and the control transfer statement has break and continue in addition to return.
In addition, the throw statement belongs to the control transfer statement. Although return, throw, break, and continue are all control transfer statements, there is a difference between them.
where return and throw transfer control of the program to their callers (invoker), and the control of break and continue is transferred within the current method.


Listing 5.

public class Test {public     static void Main (string[] args) {         System.out.println ("Return value of GetValue ():" + G Etvalue ());     }       public static int GetValue () {         try {             return 0;         } finally {             return 1;     }}}


The result of the execution of listing 5:

return value of GetValue (): 1


Listing 6. 

  public class Test {public      static void Main (string[] args) {          System.out.println ("Return value of GetValue ():" + G Etvalue ());      }         public static int GetValue () {          int i = 1;             try {             return i;        } finally {             i++;}}     }  



The result of the execution of listing 6:

return value of GetValue (): 1

Using the above analysis, we can conclude that:

The finally statement block is executed before the return statement in a try or catch.

From this, it is easy to understand that the execution result of listing 5 is 1.

Because return 1 in the Finally, statement to return 0 in the try, the statement before execution, then finally in the return 1;
After the statement executes, the control of the program is transferred to its caller main () function, and the return value is 1.

So why is the return value of listing 6 not 2, but 1?

According to the analytic Logic of listing 5, the i++ in finally;
The statement should be executed before the return I in the try;
The initial value of I is 1, then execute i++, then 2, then return I; that should be 2? How did it become 1?

Let's analyze the order of execution: there are two cases of normal execution (no exception) and exception execution (with exception). Let's take a look at the normal execution situation, as shown in 1:


Figure 1. GetValue () function Normal execution condition

We can clearly see that before the finally statement block (Iinc 0, 1) is executed, the GetValue () method saves its return value (1) to the location of the local table 1, the command to complete the task is istore_1, and then executes the finally statement block (Iinc 0 , 1), the finally statement block adds 1 to the value of the local variable table at position 0, and becomes 2; After the finally statement block is executed, the value of 1 in the local table scale is restored to the operand stack (iload_1), and the last execution of the ireturn instruction puts the value in the current operand stack ( 1) return to its caller (main). That's why the result of listing 6 is 1, not 2.

Let's look at the situation with exception execution. Does anyone ask if you don't have a catch statement in Listing 6, and where is the exception handling? I think this is a good question, in fact, even if there is no catch statement, the Java compiler compiled bytecode still has the default exception handling, do not forget, in addition to catch exceptions, there may be no need to catch exceptions (such as: RuntimeException and Error).


Figure 2. GetValue () function Exception execution condition

Listing 7.


  public class Test {public      static void Main (string[] args) {          System.out.println ("Return value of GetValue ():" + G Etvalue ());      }         @SuppressWarnings ("finally") public      static int getValue () {          int i = 1;            try {             i = 4;        } finally {             i++;             return i;}}     }


The result of the execution of listing 7:

return value of GetValue (): 5


Listing 8.

public class Test {public     static void Main (string[] args) {          System.out.println ("Return value of GetValue ():" + G Etvalue ());      }         public static int GetValue () {          int i = 1;             try {             i = 4;         } finally {             i++;         }           return i;     }}



The result of the execution of listing 8:


return value of GetValue (): 5


Let's look at a slightly more complicated example-listing 9.


Listing 9.

<strong>  </strong>public class Test {public      static void Main (string[] args) {          SYSTEM.OUT.PRINTLN (Test ());      }         public static String test () {          try {              System.out.println ("try block");                return test1 ();         } finally {             System.out.println ("finally Block");         }     }       public static String Test1 () {         System.out.println ("return statement");           Return "after Return";}     }



Results from Listing 9:

Try block return statementfinally block after return


return test1 (); This statement is equivalent to:

String tmp = Test1 (); return TMP;

In this way, it should be clear why it is the result of the implementation shown above!

On the depth discrimination of finally statement block in Java

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.