zoukankan      html  css  js  c++  java
  • try catch finally语句块中存在return语句时的运行流程

    原文链接


    题目: 下面代码运行结果是()

    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)); 
         }
    }
    

    选项:

    A、 catch语句块     和是:43           B、编译异常        
    C、 finally语句块   和是:43           D、和是:43    finally语句块 
    

    对于运行结果不理解的同学耐心看看接下来这两段代码,就会对try catch finally语句块存在return语句时的运行流程豁然开朗。

    Code one:

    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” 里的语句是在 try 语句块 “return” 之后执行的,其实不然,实际上 “finally” 里的语句是在 “return” 之前执行的。那么问题来了,既然是在之前执行,那为什么 a 的值没有被覆盖了?

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

    Code two:

    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
    */
    

    跟Code one不同的是现在finally语句块中也有return语句,那么在执行这个return时,就会更新临时栈中的值。同样,在执行完finally之后,就会通知主程序请求返回了,即将临时栈中的值取出来返回。故返回值是2。

    现在回过头来看看一开始的那段代码:

    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)); 
         }
    }
    

    过程剖析:
    ① 第16行代码因为字符串拼接是一个整体,所以必须先获取add方法的运算结果才能输出。故排除D选项。
    ②try 和 catch两语句块同时存在时,如果try中有return语句,那么后面try catch finally语句块之外的return语句就不起作用了,编译器也不会报“Unreachable code”错误。大家可以打开编译器试试。故排除B选项。
    ③ try块没有产生任何运行时异常,因此排除A选项。
    ④ finally语句块中的语句先于return语句运行,因此控制台输出“finally语句块”,然后执行return语句返回运算结果。最后回到主程序,字符串拼接完成输出“和是43”。故正确答案为C。

  • 相关阅读:
    C# -- HttpWebRequest 和 HttpWebResponse 的使用
    C# -- Lambda 表达式的使用
    ASP.NET -- WebForm -- HttpRequest类的方法和属性
    ASP.NET -- WebForm -- HttpResponse 类的方法和属性
    C# -- 索引器、枚举类型
    C#设计模式之七桥接模式(Bridge Pattern)【结构型】
    C#设计模式之六适配器模式(Adapter Pattern)【结构型】
    C#设计模式之五原型模式(Prototype Pattern)【创建型】
    C#设计模式之四建造者模式(Builder Pattern)【创建型】
    C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】
  • 原文地址:https://www.cnblogs.com/txge/p/13973577.html
Copyright © 2011-2022 走看看