异常屏蔽

直接上代码:

public class Connection implements AutoCloseable {
    public void sendData() throws Exception {
        throw new Exception("send data");
    }
    @Override
    public void close() throws Exception {
        throw new MyException("close");
    }
}

public class TryWithResource {
    public static void main(String[] args) {
        try {
            test();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static void test() throws Exception {
        Connection conn = null;
        try {
            conn = new Connection();
            conn.sendData();
        }
        finally {
            if (conn != null) {
                conn.close();
            }
        }
    }
}
output==>
basic.exception.MyException: close
    at basic.exception.Connection.close(Connection.java:10)
    at basic.exception.TryWithResource.test(TryWithResource.java:82)
    at basic.exception.TryWithResource.main(TryWithResource.java:7)
    ......

由于我们一次只能抛出一个异常,所以在最上层看到的是最后一个抛出的异常——也就是close方法抛出的MyException,而sendData抛出的Exception被忽略了。这就是所谓的异常屏蔽。由于异常信息的丢失,异常屏蔽可能会导致某些bug变得极其难以发现,程序员们不得不加班加点地找bug,如此毒瘤,怎能不除!幸好,为了解决这个问题,从Java 1.7开始,大佬们为Throwable类新增了addSuppressed方法,支持将一个异常附加到另一个异常身上,从而避免异常屏蔽。那么被屏蔽的异常信息会通过怎样的格式输出呢?我们再运行一遍刚才用try-with-resource包裹的main方法:

public class TryWithResource {
    public static void main(String[] args) {
        try (Connection conn = new Connection()) {
            conn.sendData();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
output==>
java.lang.Exception: send data
    at basic.exception.Connection.sendData(Connection.java:5)
    at basic.exception.TryWithResource.main(TryWithResource.java:14)
    ......
    Suppressed: basic.exception.MyException: close
        at basic.exception.Connection.close(Connection.java:10)
        at basic.exception.TryWithResource.main(TryWithResource.java:15)
        ... 5 more

具体原因是编译器帮我们将一个异常附加到了另一个异常上(var2.addSuppressed(var11)):

public class AppTest {
    public AppTest() {
    }

    public static void main(String[] args) {
        try {
            AppTest.Connection con = new AppTest.Connection();
            Throwable var2 = null;

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

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

    }

    static class Connection implements AutoCloseable {
        Connection() {
        }

        public void print() {
            System.err.println("print data==>");
        }

        public void close() throws Exception {
            System.err.println("auto close===>");
        }
    }
}

results matching ""

    No results matching ""