美文网首页
你真的知道finally吗?(一)

你真的知道finally吗?(一)

作者: Misout | 来源:发表于2018-01-20 21:58 被阅读81次

微信公众号:Misout的博客
如有问题或建议,请留言

一、问题

从10月份协助领导不断面试招人,其中一个问题是关于finally的问题。finally是否一定执行?try代码块和finally代码块中如果都有return语句,谁先执行,是否都会执行?。然而让我意外的是,很多人压根不清楚,非常模糊这个知识点,而且工作经验也很长。下面我们就来看看,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。

相关文章

你真的知道finally吗?(二)

参考

相关文章

  • 你真的知道finally吗?(一)

    微信公众号:Misout的博客如有问题或建议,请留言 一、问题 从10月份协助领导不断面试招人,其中一个问题是关于...

  • 你真的知道finally吗?(二)

    微信公众号:Misout的博客如有问题或建议,请留言 try catch finally的执行顺序 在上一篇文章【...

  • Big Magic 05- 恐惧其实有点无聊

    I finally realized that my fear was boring 你知道吗 ?如果一个人的恐惧...

  • 你知道吗

    你知道吗?你确定你真的知道吗?你真的确定你知道吗?你真真正正的知道,你确定你知道吗?有问题上知乎,这可以...

  • 你知道吗?

    “你知道吗?”“你真的知道吗?”“你确定你知道吗?”“你真的确定你知道吗?” 这是今年世界杯上某网站的广告,用的是...

  • 你爱哥哥,真的值得吗?

    妈想知道 你爱着的哥哥真的值得吗 妈真的很想知道 你这样做值得吗

  • 你知道吗?

    你知道吗?我真的想你了。 你知道吗?我一个人在杭州真的可以生活的很好。 你知道吗?每次收到你的消息我都很开心。 你...

  • 观《对于自己,你还是个陌生人》

    01 我们真的认识自己吗?你知道你张什么样子吗?你知道你为什么会生气吗?你知道你为什么焦虑吗?你知道你想要什么吗?...

  • 作为家长,校长,你真的知道老师喜欢什么,不喜欢什么吗? 你自己

    作为校长,你真的了解你的下属,你真的知道老师需要什么吗? 作为家长,你真的知道老师喜欢什么,不喜欢什么吗? 作为教...

  • 20年的学习还不如这1分钟

    你真的知道怎么阅读吗?你真的知道怎么学习才是最有效的吗?你真的以为时间的堆积会给你带来你想要的结果吗?显而易见很多...

网友评论

      本文标题:你真的知道finally吗?(一)

      本文链接:https://www.haomeiwen.com/subject/tjhxaxtx.html