JAVA——finally块中的代码什么时候被执行、执行的效果是什么?

来源:互联网 发布:cname 增加域名绑定 编辑:程序博客网 时间:2024/06/08 02:33

1. 当try{}有return语句,finally{}有return语句

  • 直接上程序
public class TestFinally{    public static int testFinally1()    {        try{            return 1;        }catch(Exception e){            return 0;        }finally{            System.out.println("execute finally1");            return 3;        }    }    public static void main(String[] args)     {        int result = testFinally1();        System.out.println(result);         }}
  • 编译,运行:
D:\JavaProject\demo15>javac TestFinally.javaD:\JavaProject\demo15>java TestFinallyexecute finally13
  • 总结:
  • (1)如果在try{}语句块中有return语句,而finally{}语句块中没有return语句时,finally{}块中的代码在return语句前执行。
  • 因为:由于程序执行return语句就以为着结束对当前函数的调用并跳出这个函数体,因此任何语句要执行都只能在return前执行,因此finally块里代码也是在return前执行的。
  • (2)如果在try{}语句块和finally语句块都有return语句时,finally语句块中的return语句将会覆盖函数中其他return语句。

2. finally{}中有修改return语句中的返回值

2.1 修改的返回值为基本数据类型

  • 直接上程序
public class TestFinally{public static int testFinally2()    {        int result = 1;        try{            result = 2;            return result;//执行到此处,返回值被复制        }catch(Exception e){            return 0;        }finally{            result = 3;//改变result的值与复制result的值谁先谁后?            /*从执行结果来看,是复制result的值在先,修改result的值在后。            也就是在遇到return时,就对result进行了复制,然而,            前面讲到“finally块里代码也是在return前执行的”,             即使在return前面执行finally语句块,但是在执行finally语句块            时已经对返回值result进行了复制。*/            System.out.println("execute finally2");    }    public static void main(String[] args)     {        int resultVal = testFinally2();        System.out.println(resultVal);          }}
  • 编译,运行:
D:\JavaProject\demo15>javac TestFinally.javaD:\JavaProject\demo15>java TestFinallyexecute finally22
  • 总结:程序执行到return时首先将返回值存储到一个指定的位置,其次去执行finally块,最后再返回。
  • (1)对于基本类型的数据,如果在finally块中没有return语句而存在修改返回值的语句时,在finally块中改变return的值对返回值没有任何影响。
  • 因为:在方法中,定义的基本类型数据的变量都存储在栈中,当这个函数结束以后,其对应的栈就会被回收,此时在该方法体定义的这类变量将不存在了,因此返回时不是直接返回变量的值,而是复制一份,再返回。
  • 本例方法testFinally2中调用return之前,先把result的值1存储在一个指定的位置,然后再去执行finally块中的代码,因此finally块中修改result的值不会影响到方法的返回结果。因此,在代码中的注释的猜想是正确的。

2.2 修改的返回值为引用类型

  • 直接上程序:
public class TestFinally{    public static StringBuffer testFinally3()    {        StringBuffer s = new StringBuffer("hello");        try{            return s;        }catch(Exception e){            return null;        }finally{            s.append(" world");            System.out.println("execute finally3");        }    }    public static void main(String[] args)     {        StringBuffer resultString = testFinally3();        System.out.println(resultString);       }}
  • 编译,运行:
D:\JavaProject\demo15>javac TestFinally.javaD:\JavaProject\demo15>java TestFinallyexecute finally3hello world
  • 总结:程序执行到return时首先将返回值存储到一个指定的位置,其次去执行finally块,最后再返回。
  • (2)对于引用类型的数据,定义该类型的数据变量时数据本身是存储在堆中的,在调用return之前首先把变量s的副本存储到一个指定的位置(s指向的是StringBuffer数据,这里并不是将s指向的数据存储到指定的位置,只是将“指针”s存到了其他地方,但还是指向的是堆内存的StringBuffer数据),由于s为引用类型,因此在finally块中修改s将会修改程序的返回结果。这一点从指针的角度更容易理解。

3. finally语句是不是一定会执行?答案:不一定会执行。

3.1 当程序在进入try语句之前就出现异常时,会直接结束,不会执行finally块中的语句的代码。

public class Test{    public static void testFinally()    {        int i = 5/0;        try{            System.out.println("try block");        }catch (Exception e){            System.out.println("catch block");        }finally{            System.out.println("finally block");        }    }    public static void main(String[] args)    {        testFinally();    }}
  • 编译,运行:
D:\JavaProject\demo15>javac TestFinally.javaD:\JavaProject\demo15>java TestFinallyException in thread "main" java.lang.ArithmeticException: / by zero        at TestFinally.testFinally(TestFinally.java:5)        at TestFinally.main(TestFinally.java:16)

3.2 当程序在try块中强制退出时也不会去执行finally块中的代码。

public class Test{    public static void testFinally()    {        try{            System.out.println("try block");            System.exit(0);        }catch (Exception e){            System.out.println("catch block");        }finally{            System.out.println("finally block");        }    }    public static void main(String[] args)    {        testFinally();    }}
  • 编译,运行:
D:\JavaProject\demo15>javac TestFinally.javaD:\JavaProject\demo15>java TestFinallytry block

参考:《Java程序员面试笔试宝典》

1 0
原创粉丝点击