try-catch-finally流程详解及相关使用、拓展

执行流程

  • try中没有异常(不到catch中):
    • finally中无return:
      • 返回的值是在try中该变量的值,与finally中赋值与否 无关
    • finally中有return:
      • 返回finally中的值,与try中的无关

  • try中有异常(到catch中去执行):
    • finally中无return
      • 返回的值是在catch中该变量的值,与finally中赋值与否 无关
    • finally中有return:
      • 返回finally中的值,与catch中的无关

综上:如果finally块中有return 语句,则try或catch中的返回语句无效。

提问:这么复制的执行流程,使用起来如何才能避免被坑?
  在《阿里巴巴Java开发手册》中强制要求 不要在 finally 块中使用 return ,try 块中的 return 语句执行成功后,并不马上返回,而是继续执行 finally 块中的语句,如果此处存在 return 语句,则在此直接返回,无情丢弃掉 try 块中的返回点。

代码用例

//第一种情况
	@Test
    public void tryCatchFinallyTest(){
        System.out.println(TestTryCatchFinally.tryCatchFinally());//in finally
        System.out.println(TestTryCatchFinally.tryCatchFinally1());//in try
    }
    static String tryCatchFinally(){
        String s;
        try {
            s="in try";
            return s;
        }catch (Exception e){
            s="in catch";
            return s;
        }finally {
            s="in finally";
            return s;
        }
    }
    static String tryCatchFinally1(){
        String s;
        try {
            s="in try";
            return s;
        }catch (Exception e){
            s="in catch";
            return s;
        }finally {
            s="in finally";
        }
    }
//第二种情况
@Test
    public void tryCatchFinallyTest(){
        System.out.println(TestTryCatchFinally.tryCatchFinally());//in finally
        System.out.println(TestTryCatchFinally.tryCatchFinally1());//in catch
    }
    static String tryCatchFinally(){
        String s;
        try {
            s="in try";
            int i=1/0;
            return s;
        }catch (Exception e){
            s="in catch";
            return s;
        }finally {
            s="in finally";
            return s;
        }
    }
    static String tryCatchFinally1(){
        String s;
        try {
            s="in try";
            int i=1/0;
            return s;
        }catch (Exception e){
            s="in catch";
            return s;
        }finally {
            s="in finally";
        }
    }

JDK 7后的try-with-resources介绍及用例

try-with-resources 可以自动完成像 finally 块中对资源关闭的动作,但前提是对应的资源类实现了 AutoCloseable 接口

@Test
    public void tryWithResource() {
        try (Connection temp = new Connection()) {
            temp.sentData();
            //sentData method
            //close method
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
class Connection implements AutoCloseable {
    public void sentData() {
        System.out.println("sentData method");
    }

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

编译后的 .class 文件

@Test
    public void tryWithResource() {
        try {
            Connection temp = new Connection();
            Throwable var2 = null;

            try {
                temp.sentData();
            } catch (Throwable var12) {
                var2 = var12;
                throw var12;
            } finally {
                if (temp != null) {
                    if (var2 != null) {
                        try {
                            temp.close();
                        } catch (Throwable var11) {
                            var2.addSuppressed(var11);
                        }
                    } else {
                        temp.close();
                    }
                }

            }
        } catch (Exception var14) {
            var14.printStackTrace();
        }

    }

其原理在编译后的文件中可以看到,自动为我们生成了 finally 代码块来完成关闭功能。

var2.addSuppressed(var11); 的作用
  addSuppressed的使用,是为了避免在抛出多个异常的情况下,最上层异常会覆盖下层异常,导致下层抛出的异常消失,进而导致异常定位失败的情况。使用 addSuppressed 可以把多层的异常全部显示出来,方便对异常的定位。

必须使用finally的情况

  1. 必须回收自定义的 ThreadLocal 变量,因为在多线程环境下,大量的 ThreadLocal 变量会导致内存泄漏或后续业务逻辑的问题,需要在 finally 中回收(使用 ThreadLocal.remove() 方法)
发布了91 篇原创文章 · 获赞 54 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/BigBug_500/article/details/103466049