欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  Java

Java中finally与return的执行顺序解析(代码示例)

程序员文章站 2022-04-01 08:54:25
...
本篇文章给大家带来的内容是关于Java中finally与return的执行顺序解析(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

都知道,finally的执行特点

1、不管有木有出现异常,finally块中代码都会执行;

2、当try和catch中有return时,finally仍然会执行。

那么问题来了,执行顺序是怎么样的呢?

一个简单的测试类及反编译后的字节码:

public class Test {
         publicstatic void main(String[] args) {
             System.out.println(test());
         }
 
         publicstatic int test() {
                   try{
                            System.out.println("Codesin try block.");
                            return0;
                   }catch (Exception e) {
                            System.out.println("Codesin catch block.");
                            return100;
                   }finally {
                            System.err.println("Codesin finally block.");
                   }
         }
}
/*
 public static int test();
   Code:
      0: getstatic     #2                  // Fieldjava/lang/System.out:Ljava/io/PrintStream;
      3: ldc           #5                  // String Codes in try block.
      5: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      8: iconst_0
      9: istore_0
     10: getstatic     #7                  // Field java/lang/System.err:Ljava/io/PrintStream;
     13: ldc           #8                  // String Codes in finallyblock.
     15: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     18: iload_0
     19: ireturn
     20: astore_0
     21: getstatic     #2                  // Fieldjava/lang/System.out:Ljava/io/PrintStream;
     24: ldc           #10                 // String Codes in catchblock.
     26: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     29: bipush        100
     31: istore_1
     32: getstatic     #7                  // Fieldjava/lang/System.err:Ljava/io/PrintStream;
     35: ldc           #8                  // String Codes in finallyblock.
     37: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     40: iload_1
     41: ireturn
     42: astore_2
     43: getstatic     #7                  // Fieldjava/lang/System.err:Ljava/io/PrintStream;
     46: ldc           #8                  // String Codes in finallyblock.
     48: invokevirtual #6                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     51: aload_2
     52: athrow
*/

可以将我们编写的代码和编译后的字节码做一下对比:

Java中finally与return的执行顺序解析(代码示例)

发现虚拟机为我们做了好多事,它将finally语句块插到try,catch与return语句之间了。这也就是为什么无论异常与否,返回与否,finally都会执行的原因。既然,finally都会执行,那么在finally中return什么就是什么。既然finally前面所有return都是无效的,return还有什么意义呢,所以,实际中finally块是不允许返回的。eclipse编译器会提示warning:finallyblock does not complete normally。

几种情形的测试代码

try{ return; }catch(){} finally{} return;

测试代码:

1.基本数据类型

   public static int test1(){
      int a = 10;
      try{
         a = 20;
         return a;
      }catch(Exception e){
         //other codes.
      }finally{
         a += 5;
         //other codes.
      }
      return a;
   }//最终返回值为20

2.引用数据类型改变引用对象的值

   public static StringBuffer test2(){
      StringBuffer sb = new StringBuffer("abc");
      try{
         return sb;
      }catch(Exception e){
         //other codes.
      }finally{
         sb.append("DEF");
         //other codes.
      }
      return sb;
   }//最终返回中内容为abcDEF
  public static StringBuffer test3(){
      StringBuffer sb = new StringBuffer("abc");
      try{
         return sb;
      }catch(Exception e){
         //other codes.
      }finally{
         sb = new StringBuffer("DEF");
         //other codes.
      }
      return sb;
   }//最终返回值中的内容为abc

在此种情形的测试中可以发现,在finally之前若有return语句,finally对返回变量无论做什么修改,变量本身是不会再变的,比如为基本类型的变量重新赋值,或是为引用类型的变量重新指定引用都是不会记录到返回值中的。但是finally中的语句会执行,那么在finally中对引用类型的变量指向的对象内容是可以修改的,且修改有效。此种情形可以这样理解,遇到return语句,虚拟机为return的值盖了一套房子,房子能随便拆吗?不能。但是房子里面的人是可以变的。基本数据类型和引用类型的变量本身就是房子,引用类型变量指向的对象中的内容就是房子中的人。

有这样一个小测试:

   public static int test(int num){
      int a = 10;
      try{
         return a;
      }catch(ArithmeticException e){
         a = 20;
         return a;
      }finally{
         a = 30;
         return a;
      }
   }

1.1 try 块中没有异常时返回值是多少?

1.2 try块中有ArithmeticException异常时返回值是多少?

1.3 try块中有其他异常时返回值是多少?

答案:全部是30.原因是在执行完try块中return之前的代码后,jvm在return之间插入了finally块中的代码,finally块中含有return,那么就直接返回了。

相关推荐:

Java中try与finally以及return语句的执行顺序

举例说明Java中代码块的执行顺序

以上就是Java中finally与return的执行顺序解析(代码示例)的详细内容,更多请关注其它相关文章!