finally代码块在return前执行?

本文学习finally代码块和return执行顺序问题。

上一章

finally

finally代码块通常配合try、catch一起出现。 finally块中定义的代码总是在try和任何catch块之后、方法完成之前运行。不管是否抛出或捕获异常 finally 块都会执行。

何时finally代码块不会执行

(1)如果在try语句之前就执行return,这样finally语句就不会执行,也就说明finally被执行就必须进入try语句。 (2)System.exit(0);这是JVM提供的强制关闭虚拟机,自然finally代码块不会被执行。

例子:

@Test
public void test1() {
    System.out.println("执行业务");
    if (true) {
        //直接return 通不过编译检查的
        return;
    }
    try {
        System.out.println("dosomething");
    } finally {
        System.out.println("执行finally");
    }
}
@Test
public void test2() {
    System.out.println("执行业务");
    //结束虚拟机
    System.exit(0);
    try {
        System.out.println("dosomething");
    } finally {
        System.out.println("执行finally");
    }
}
复制代码

两个例子结果都是一样的,不执行finally代码块。 image.png

finally和return

这里两个方面分析,finally代码块和return的代码孰先孰后。finally是在return成功返回之前还是之后执行的。

public Integer add(){
    Integer i = 10;
    try {
        return i = i+100;
    }finally {
        System.out.println("i的值为=>"+i);
    }
}

@Test
public void test3(){
    Demo01 demo01 = new Demo01();
    System.out.println(demo01.add());
}
复制代码

image.png

这个例子足够说明了
①finally代码块的执行在return代码的后面
②在方法完全执行(也就是成功返回)之前


finally代码块中return会怎样?

public String str(){
    try{
        System.out.println("try执行");
        return "try return";
    }finally {
        System.out.println("finally执行");
        return "finally return";
    }
}
@Test
public void test(){

    Demo01 demo01 = new Demo01();
    System.out.println(demo01.str());

}
复制代码

image.png

这个简单例子只为说明,finally中的return会覆盖try中的return。

finaly可以影响try中的return值吗?

此处意思是如果finally对return的结果进行修改会不会影响return结果。
理解关键在于 java的值传递。对于基本数据类型只有值,对于引用类型传递的是引用地址。

第一种情况:finally不会改变return结果

关于基本数据类型的包装类型和String,如果修改他们的值会直接改变引用地址。 这个是jvm内存模型,简单理解。

image.png

如上图 比如 Integer i = 10; i = i + 10; 其实这个加操作会做哪些事呢?
①首先会在堆内存创建一个新的Integer对象 20
②将新建的Integer对象的内存地址赋给i

public int xxx(Integer i) {

    try {
        System.out.println("try  原结果=>"+i);
        return i;
    } finally {
        if (i >= 16) {
            i = i & ((1 << 4) - 1);
            System.out.println("finally 修改后=>"+i);
        }
    }
}

@Test
public void test5(){
    Demo01 demo01 = new Demo01();
    System.out.println("最终结果=>"+demo01.xxx(20));

}
复制代码

image.png 这里可以得出一个结论,关于基本数据类型return的时候会记录被return结果的值,对于引用类型return会记录返回结果的引用地址。

finally会修改return结果:

简单理解

image.png

@Data
@AllArgsConstructor
class Person{
    int age;
    String name;
}
public Person xxx2(Person p) {
    try {
        System.out.println("try  原结果=>"+p);
        return p;
    } finally {
        if (p.getName().equals("abc")) {
            p.setName("123");
            System.out.println("finally 修改后=>"+p);
        }
    }
}
@Test
public void test52(){
    Demo01 demo01 = new Demo01();
    System.out.println("最终结果=>"+demo01.xxx2(new Person(23,"abc")));

}
复制代码

image.png 可以发现修改了return的结果,对于引用类型虽然return记录了return结果的引用地址值,但是 所指向的对象是可以被修改的。

接下来还有一些情况,比如说在catch中的操作对return的影响,或者在catch中return,当然catch专心做捕获异常工作,一般做一些日志记录。

猜你喜欢

转载自juejin.im/post/7081317835930075173
今日推荐