• 'try(A a = new A())' VS 'try finally'


    实现了AutoCloseable接口的类,可以在try的时候直接实例化对象。try代码块完成之后,自动调用close方法,相当于在finally里主动调用。但是出现异常后的流程和try finally有什么不同呢? 下面写代码测试一下。

    首先定义一个类Cat,实现AutoCloseable接口

    class Cat implements AutoCloseable{
    	void sayHello() throws Exception {
    		Utils.println("calling sayHello(), I will throw an exception");
    		throw new Exception("Exception in sayHello() ");
    	}
    
    	@Override
    	public void close() throws Exception {
    		Utils.println("I'm closing, I will throw an exception");
    		throw new Exception("Exception in close()");
    	}
    }
    

    我们的这个Cat有以下特点:

    • sayHello方法会抛出异常
    • close方法也会抛出异常

    test v1: 'try(Cat cat = new Cat())' VS 'try finally'

    没有catch(不要被外层的catch迷惑,那只是为了打印异常)

    static void testV1(){
        Utils.println("----try(Cat cat = new Cat())-----");
        try{
            try(Cat cat = new Cat()){
                cat.sayHello();
            }
    
        }catch (Exception e){
            Utils.println("cache error in main (" + e + "), let's see its stack trace");
            Utils.printStackTrace(e);
        }
        Utils.println("--------------");
    
        Utils.println("----try finally-----");
        try{
            Cat cat = null;
            try{
                cat = new Cat();
                cat.sayHello();
            }finally {
                if(cat != null){
                    cat.close();
                }
            }
        }catch (Exception e){
            Utils.println("cache error in main (" + e + "), let's see its stack trace");
            Utils.printStackTrace(e);
        }
        Utils.println("--------------");
    }
    

    结果输出:

    ----test v1----------------------------------------
    ----try(Cat cat = new Cat())-----
    calling sayHello(), I will throw an exception
    I'm closing, I will throw an exception
    cache error in main (java.lang.Exception: Exception in sayHello() ), let's see its stack trace
    java.lang.Exception: Exception in sayHello() 
    	at Cat.sayHello(Cat.java:4)
    	at Test.testV1(Test.java:16)
    	at Test.main(Test.java:4)
    	Suppressed: java.lang.Exception: Exception in close()
    		at Cat.close(Cat.java:10)
    		at Test.testV1(Test.java:17)
    		... 1 more
    --------------
    ----try finally-----
    calling sayHello(), I will throw an exception
    I'm closing, I will throw an exception
    cache error in main (java.lang.Exception: Exception in close()), let's see its stack trace
    java.lang.Exception: Exception in close()
    	at Cat.close(Cat.java:10)
    	at Test.testV1(Test.java:33)
    	at Test.main(Test.java:4)
    --------------
    

    结论

    • try(Cat cat = new Cat())
      • try代码块完成之后会自动调用close
      • close抛出的异常,被Suppressed了,外层捕获的只有sayHello的异常,但通过堆栈可以找到这个Suppressed的异常
    • try finally
      • 外层捕获的是在finally执行close时抛出的异常,sayHello的异常完全不见了。

    test v2: 'try(Cat cat = new Cat()) catch{}' VS 'try catch finally'

    有catch,并且catch里再抛出异常

    static void testV2(){
        Utils.println("----try(Cat cat = new Cat()) catch-----");
        try{
            try(Cat cat = new Cat()){
                cat.sayHello();
            } catch (Exception e) {
                Utils.println("cached err (" + e.getMessage() + "), I will throw an exception again");
                throw new Exception("Exception in catch", e);
            }
    
        }catch (Exception e){
            Utils.println("cache error in main (" + e + "), let's see its stack trace");
            Utils.printStackTrace(e);
        }
        Utils.println("-----------------------------------------");
    
        Utils.println("----try catch finally--------------------");
        try{
            Cat cat = null;
            try{
                cat = new Cat();
                cat.sayHello();
            } catch (Exception e) {
                Utils.println("cached err (" + e.getMessage() + "), I will throw an exception again");
                throw new Exception("Exception in catch", e);
            }finally {
                if(cat != null){
                    cat.close();
                }
            }
        }catch (Exception e){
            Utils.println("cache error in main (" + e + "), let's see its stack trace");
            Utils.printStackTrace(e);
        }
        Utils.println("-------------------------------------------");
    }
    

    结果输出

    ----test v2------
    ----try(Cat cat = new Cat()){} catch{}-----
    calling sayHello(), I will throw an exception
    I'm closing, I will throw an exception
    cached err (Exception in sayHello() ), I will throw an exception again
    cache error in main (java.lang.Exception: Exception in catch), let's see its stack trace
    java.lang.Exception: Exception in catch
    	at Test.testV2(Test.java:50)
    	at Test.main(Test.java:8)
    -----------------------------------------
    ----try catch finally--------------------
    calling sayHello(), I will throw an exception
    cached err (Exception in sayHello() ), I will throw an exception again
    I'm closing, I will throw an exception
    cache error in main (java.lang.Exception: Exception in close()), let's see its stack trace
    java.lang.Exception: Exception in close()
    	at Cat.close(Cat.java:10)
    	at Test.testV2(Test.java:70)
    	at Test.main(Test.java:8)
    -------------------------------------------
    ---------------------------------------------------------------------
    

    结论

    • try(Cat cat = new Cat()) catch
      • catch之前就调用了close(符合try代码块完成之后会自动调用close这个结论)
      • catch到的是sayHello的异常,close抛出的异常依然被Suppressed了
      • catch中再次抛出的异常被外层捕获
    • try catch finally
      • 先走catch,再走finally,所以catch捕获的是sayHello的异常
      • catch中再次抛出的异常不见了,外层捕获的是在finally执行close时抛出的异常。

    测试代码地址:https://github.com/kongxiangxin/pine/tree/master/auto-closeable

  • 相关阅读:
    每日日报
    每日日报
    每日日报
    每日日报
    每日日报
    每日日报
    SpringMVC--->注解开发(各种注解的适应方法)
    SpringMVC--->入门(理解)
    SpringMVC--->Servlet回顾
    IDEA--->Maven不能继承HttpServlet
  • 原文地址:https://www.cnblogs.com/default/p/11909847.html
Copyright © 2020-2023  润新知