美文网首页
重温try-catch-finally

重温try-catch-finally

作者: 艺超51iwowo | 来源:发表于2021-04-16 23:29 被阅读0次

    本周一个重要的收获是自己在代码中,引入了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

    相关文章

      网友评论

          本文标题:重温try-catch-finally

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