关于finally

 

finally代码块一定会执行吗?

答案当然是否定的。原因显而易见,在如下的情况下,finally代码块不会执行。

  • 在try代码块之前,程序出现异常,不会执行到finally代码块。
  • 在try代码块之前,程序返回,不会执行finally代码块。
  • 在try代码块中,如果主动执行System.exit(0)语句,不会执行finally代码块。
  • 在没执行到finally代码块之前,突然JVM异常退出,例如断电,finally不会执行。

关于try中return后的返回值问题

代码示例

// 方法返回值是3 or 4?
public int finallyCase() {
    int i = 1;
    try {
        i = 3;
        System.out.println("try block,i="+i);
        return i;
    } finally {
        i = 4;
        System.out.println("finally block,i=" + i);
    }
}

请回答输出结果?结果如下:

try block,i=3
finally block,i=4
方法返回值:3

为什么返回值是3而不是4?是不是出于你的意外?而且finally代码块中语句的确在try代码块return i之前得到执行了,finally代码块中的i也确实变成了4,可是为什么方法返回值仍然是3呢?

通俗的说就是:JVM会把try或者catch代码块中的返回值保留,再来执行finally代码块中的语句,等到finally代码块执行完毕之后,再把之前保留的返回值给返回出去。本质上是由JVM在执行指令过程中的导致的。想弄懂具体原因,请阅读你真的知道finally吗?(二)

换个方式来问你:关于try中return后的返回值问题

在上一个章节示例中,你是否已经知道返回值问题。关于此问题,我们继续看一个变种示例:

// 在finally方法中多了一个return语句,返回值是3 or 4?
public int finallyCase() {
    int i = 1;
    try {
        i = 3;
        System.out.println("try block,i="+i);
        return i;
    } finally {
        i = 4;
        System.out.println("finally block,i=" + i);
        return i;
    }
}

请回答输出结果?结果如下:

try block,i=3
finally block,i=4
方法返回值:4

为什么现在是4?前面不是说在try中i的值会暂存吗?
但这里请注意,finally代码块是在try中return之前执行。i变成了4,然后直接return了,所以try中的return语句实际是没有被执行的。因此返回值为4。

引用类型-try中return后的返回值问题

前面我们已经研究了基本数据类型try和finally中return返回值的问题,下面我们再来看看引用类型的返回值问题,又会有哪些不同呢?

// 返回的user对象,姓名是u1还是u2
private static User test1() {
    User user = new User("u1");
    try {
        return user;
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        user = new User("u2");
    }
    return null;
}

// 返回的user对象,姓名是u1还是u2
private static User test2() {
    User user = new User("u1");
    try {
        return user;
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        user.setName("u2");
    }
    return null;
}

请问上面两个方法分别执行后,user对象的姓名值是多少?
答案

test1()方法:u1
test2()方法:u2

是不是又会令你百思不得其解?
原因其实和上面非常相似。对于引用类型,在try执行return之前,会暂存一份对象的引用,finally执行完后,将暂存的引用直接返回,所以test1方法中,虽然new出了一个新的User对象,但try中暂存的还是u1的对象,所以结果为u1。而test2方法中finally直接给对象的属性赋值,改变的并非对象的引用,所以返回的对象姓名为u2。

结论

  • 在正常try能全部执行的情况下,finally都会执行,而程序还没执行到try,则finally不一定执行;
  • 对于基本数据类型,在try中return,在finally执行前会把结果暂存起来,即使在finally中有修改也以try中保存的值为准,但如果是引用类型,修改的属性会以finally修改后的为准;
  • 如果try/finally都有return,直接返回finally中的return。



作者:Misout
链接:https://www.jianshu.com/p/73a40069ac05
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

全部评论

相关推荐

永联 dsp工程师 15k*15 双非硕士
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务