JAVA学习笔记(异常处理)

关于finally块的运行顺序,在学习阶段不是很明确。查询了一些资料后,大概可以得出以下结论:“finally块是在下级函数向上级调用的函数跳转前(无论是通过return还是throw exception的方式回到调用函数)执行”,具体参照以下两个示例。

    public static void main(String[] args) {
        test t=new test();
        System.out.println(t.f());
    }   
    public String f() {
        try{
            System.out.println("try block");
            return f2();
        }
        finally{
            System.out.println("finally block");
            return "finally";
        }
    }
    public String f2(){
        System.out.println("returning");
        return "return";
    }

此时的输出结果为

try block
returning
finally block
finally

分析:try块执行,运行到f()中的return**这行,按惯例先执行return语句后半部分(用于计算return的返回值),输出returning之后,开始正式执行return语句*,将返回值*return存在一个临时区域里,并在程序正式由f()跳转回main()之前,执行finally块的语句。若finally块内有返回值,则将此返回值替换原来临时变量区内的返回值。因此最后输出的不是return而是finally。

类似的:

public static void main(String[] args) {
        test t=new test();
        try{
            System.out.println(t.f());
        }
        catch(Exception e){}
    }

    public String f() {
        try{
            System.out.println("try block");
            int a=5/0;
        }
        catch(Exception e){
            System.out.println("exception block");
            throw e;
            //return "exception"
        }
        finally{
            System.out.println("finally block");
            return "finally";
        }

输出结果仍为:

try block
exception block
finally block
finally

此时由catch块捕获并抛出异常,但finally块仍把“finally”作为返回值返回给了main函数,并由main函数打印出来。用注释掉的return部分替换原有的catch模块,结果也是一样的。

但是在finally块中修改返回值对应的变量(而不调用return语句),实际的返回值不会被修改。

public static void main(String[] args) {
        test t=new test();
        try{
            System.out.println(t.f());
        }
        catch(Exception e){}
    }

    public String f() {
        String s;
        try{
            System.out.println("try block");
            return s="return";
        }
        finally{
            System.out.println("finally block");
            s="finally";
        }
    }

输出为

try block
finally block
return

可见最后被返回的变量s没有被修改成finally。这里要说道JAVA的值传递特性。JAVA没有真正意义上(像C++)一样的引用传递。而由于string类型的不可变性,对s的修改都会采用新建一个字符串并将s引用(指针)修改到新建字符串上。然而,try块中调用的return已经反回了s的值(存在临时区域内),即return字符串对应的地址,此时将s的值修改了也没有实际作用。

考虑JAVA的值传递特性,我们可以推测,对于int之类的基础类型的返回值,在finally块修改而不return返回值变量,对函数返回值没有影响(因为return已经将变量内存储的值存入临时区域内)。但是对于class类型的变量返回值,如果在finally块内修改类的成员变量等,真正的返回值中的成员变量也会对应被修改。

发布了39 篇原创文章 · 获赞 4 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章