zoukankan      html  css  js  c++  java
  • 记一下一道关于finally的题

     题目:

    public class Test{ 
        public int add(int a,int b){   
             try {
                 return a+b;      
             } 
            catch (Exception e) {  
                System.out.println("catch语句块");
             }
             finally{ 
                 System.out.println("finally语句块");
             }
             return 0;
        } 
         public static void main(String argv[]){ 
             Test test =new Test(); 
             System.out.println("和是:"+test.add(9, 34)); 
         }
    }

    结果是:

    finally语句块
    和是:43

    为什么呢?首先,这个字符串的相加,涉及变量,所以底层是通过StringBuilder来进行的,所以先进入test.add(9, 34)。

    然后,要个道理要知道,这是来自《The Java Tutorials》文档中的一段描述Finally关键字的话:

    上面说到,finally块总是会在try块结束后执行,来保证finally块一定会执行,哪怕是有无法预测的异常抛出。但确实这个finally模块不仅仅是在异常控制中有所作用,它允许编程者在代码运行return,continue或者是break语句之前进行些其他的工作,像cleanup某些资源的代码。

    但是!如果JVM(Java虚拟机)在执行try或者catch块的代码的时候退出了,那么finally块中的代码也就可能不会被执行到了,就像线程执行的时候被打断或者是直接被杀死这类的情况。

    总结一下,实验的结论就是:finally块中的语句总是会在控制转移语句(break、continue、return等)执行之前执行!除非是遇到JVM退出的情况,finally块中的内容才不会被执行。

    所以,这里在要执行try中的return之前,先去执行了finally中的打印语句,就有了这样的输出。

    再来看两个特殊的例子

    public abstract class Test {
        public static void main(String[] args) {
            System.out.println(beforeFinally());
        }
         
        public static int beforeFinally(){
            int a = 0;
            try{
                a = 1;
                return a;
            }finally{
                a = 2;
            }
        }
    }
    /**output:
    1
    */

    从结果上看,貌似`finally` 里的语句是在`return` 之后执行的,其实不然,实际上`finally` 里的语句是在在`return` 之前执行的。那么问题来了,既然是在之前执行,那为什么`a` 的值没有被覆盖了?


    实际过程是这样的:当程序执行到try{}语句中的return方法时,它会干这么一件事,将要返回的结果存储到一个临时栈中,然后程序不会立即返回,而是去执行finally{}中的程序, 在执行`a = 2`时,程序仅仅是覆盖了a的值,但不会去更新临时栈中的那个要返回的值 。执行完之后,就会通知主程序“finally的程序执行完毕,可以请求返回了”,这时,就会将临时栈中的值取出来返回。这下应该清楚了,要返回的值是保存至临时栈中的

    再来看一个例子,稍微改下上面的程序:

    public abstract class Test {
        public static void main(String[] args) {
            System.out.println(beforeFinally());
        }
         
        public static int beforeFinally(){
            int a = 0;
            try{
                a = 1;
                return a;
            }finally{
                a = 2;
                return a;
            }
        }
    }
    /**output:
    2
    */

    在这里,finally{}里也有一个return,那么在执行这个return时,就会更新临时栈中的值。同样,在执行完finally之后,就会通知主程序请求返回了,即将临时栈中的值取出来返回。故返回值是2。

  • 相关阅读:
    Angularjs html文本显示
    .net与.net core学习目录
    数据库学习目录
    WCF学习目录
    sql学习目录
    EF学习目录
    git for Windows
    图谱论(Spectral Graph Theory)基础
    2017机器学习相关会议时间
    数值分析教材统计
  • 原文地址:https://www.cnblogs.com/wangshen31/p/10483631.html
Copyright © 2011-2022 走看看