• 技术文章 >Java >java教程

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

    不言不言2018-09-11 14:16:02原创790
    本篇文章给大家带来的内容是关于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
    */

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

    20160926221110174.png

    发现虚拟机为我们做了好多事,它将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的执行顺序解析(代码示例)的详细内容,更多请关注php中文网其它相关文章!

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    专题推荐:Java finally return
    上一篇:使用Spring Cloud Netflix Zuul代理网关访问后台REST服务的实现(代码) 下一篇:SpringBoot动态管理定时任务的实现代码
    大前端线上培训班

    相关文章推荐

    • try finally 妙用,防止内存泄漏_javascript技巧• Finally Redis collections are iterable• java中finally语句的实例详解• Java中try与finally以及return语句的执行顺序• JavaScript异常处理之try catch finally的实例分析

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网