重温try-catch-finally

本文探讨了在Java 7中使用try-with-resource语句时,如何与finally代码块配合,并揭示了资源关闭时机。通过实例和实验,总结了引用类型、基本类型和包装类型的处理规则。同时提到了finally的执行特点和潜在问题,如代码规约检查的提示。
摘要由CSDN通过智能技术生成

本周一个重要的收获是自己在代码中,引入了java7的try-with-resource方法。该方法实际上用的比较少,和同事讨论的时候,有一个问题比较有趣,如果同时使用try-with-resource和finally,那资源是在finally之前关闭的,还是之后呢?

try-with-resource下finally代码块的执行顺序

示例代码如下:

注意: 使用try-with-resource的类,必须实现AutoCloseable接口。

public class TryWithResourceTest {

    public static void main(String[] args) {
        try (MyTest myTest = new MyTest()) {
            System.out.println("main");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("finally");
        }
    }

    private static class MyTest implements  AutoCloseable {

        @Override
        public void close() throws Exception {
            System.out.println("myTest.close");
        }
    }
}

执行结果如下:

image-20210321065844425

可以看到,close方法是在正常的finally之前执行的,也就是之前大家广知的finally代码块是最后执行的。

finally代码块的一些其他注意事项
1. finally代码块一定会执行吗?

执行方法后,直接exit,此时finally模块无法正常执行。

image-20210321070516185

2. finally代码块中如果对return中的变量做了修改,那返回结果会修改吗?

2.1 先看引用类型,在MyTest类中增加String 类型的text和Integer类型的number字段,示例代码如下

 private static MyTest executeReference() {
        MyTest myTest = new MyTest();
        try {
            myTest.setText("try-return");
            myTest.setNumber(10);
            return myTest;
        } finally {
            myTest.setText("finally-return");
            myTest.setNumber(20);
        }
    }

在finally模块中,对返回值做了修改,输出结果如下

image-20210321071707539

此时,finally模块会修改try中返回的值。

2.2 但是测试发现,如果变为基本类型或者包装类型,情况又不一样

测试代码:

private static Integer executeBox() {
        Integer integer = new Integer(300);
        try {
            return integer;
        } finally {
            integer = new Integer(400);
        }
    }

    private static int executeUnBox() {
        int integer = 300;
        try {
            return integer;
        } finally {
            integer = 400;
        }
    }

image-20210321071852239

此时的返回结果,是以try中的返回结果为准。

2.3 最后再来看一下基本类型数组的情况

private static int[] executeArray() {
        int[] test = new int[] {0, 1};
        try {
            return test;
        } finally {
            test[1] = 10;
        }
    }

此时的测试结果,对应位置的数据已经被finally模块修改过了。

image-20210321072353664

所以,

  1. 如果是引用类型,finally可以对其中的值进行修改。
  2. 如果是基本类型和其包装类型,finally不会进行修改,以try语句中的为准
3. finally代码块中如果也有return语句,那会返回什么结果呢?

针对上述情况中,基本类型和包装类型的测试代码中,直接在finally模块中,执行return语句。

 private static Integer executeBox() {
        Integer integer = new Integer(300);
        try {
            return integer;
        } finally {
            integer = new Integer(400);
            return integer;
        }
    }

    private static int executeUnBox() {
        int integer = 300;
        try {
            return integer;
        } finally {
            integer = 400;
            return integer;
        }
    }

此时的测试结果会是finally中最后修改的值

image-20210321072900945

但是实际情况下,此时如果有安装Alibaba代码规约检查工具,会有对应的提示,这种情况容易触发问题,需引起重视。

image-20210321072954699

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

51iwowo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值