Who decides what exceptions get suppressed?

a 夏天 提交于 2019-12-05 18:30:02

This is not arbitrary—the suppressed exceptions are the ones that would otherwise mask the main exception that caused the try block to fail—and that's the ones in the finally block. This feature ensures that you get all the exceptions thrown in the whole construct, but the one you catch will be the more important one.

You don't get to choose what gets suppressed. The method is there, for sure, otherwise the whole thing wouldn't work. If you like, you can write your own exception handling code and use addSuppressed ad libitum.

Why new reply:

  1. more clarifications (at least I needed them once reading, especially on the catch side)
  2. added code
  3. added use-case / example for addSuppressed usage (catch)

Case-by-case:

  1. old try-catch-finally (or try-finally) will suppress exceptions from all but finally block. Also, nothing will be in suppressed exceptions list, if you touch it, regardless of whether something was suppressed or not.
  2. try-with-resources-finally will propagate try exception, with finally one being in suppressed list.
  3. try-...-catch-finally works similarly. If catch throws, it suppresses try exception making it lost, unless you use addSupressed() on catch exception manually (tying original exception to new one being thrown). I believe this to be the case accepted answer covers in last paragraph.

public class WhichIsSupressedTryCatchOrFinally {

public static void main(String[] args) {
    try {
//            tryOrFinally(); // throws finally, try one is lost
//            tryCatchOrFinally(); // as above, no suppression info

//            tryWithResourcesOrFinally(); // throws try, adds finally one to it though automatically
        tryWithResourcesCatchOrFinallyCatchThrows();
        tryWithResourcesCatchOrFinallyByHand(); // throws catch, but adding "by hand" try, adds finally also
    } catch (Exception e) {
        e.printStackTrace();
        // System.out.println(Arrays.toString(e.getSuppressed())); -> not needed!
    }
}

static class AResource implements AutoCloseable {

    @Override
    public void close() throws NumberFormatException {
        throw new NumberFormatException("did not see that one coming, did'ya?");
    }
}
private static void tryWithResourcesOrFinally() throws FileNotFoundException {
    try (AResource a = new AResource()) {
        throw new FileNotFoundException("try");
    }
}

private static void tryWithResourcesCatchOrFinallyCatchThrows() throws Exception {
    try (AResource a = new AResource()){
        throw new IOException("try");
    } catch (Exception e) {
        throw new NoSuchElementException("catch");
    }
}

private static void tryWithResourcesCatchOrFinallyByHand() throws Exception {
    try (AResource a = new AResource()){
        throw new IOException("try");
    } catch (Exception e) {
        NoSuchElementException aCatch = new NoSuchElementException("catch");
        aCatch.addSuppressed(e);
        throw aCatch;
    }
}

private static void tryOrFinally() throws Exception {
    try {
        throw new IOException("try");
    } finally {
        throw new Exception("finally");
    }
}

private static void tryCatchOrFinally() throws Exception {
    try {
        throw new IOException("try");
    } catch (Exception e) {
        throw new NoSuchElementException("catch");
    } finally {
        throw new Exception("finally");
    }
}

}

So, you don't choose what gets suppressed, and addSuppressed is to make stack traces more complete.

Outputs:

  1. try - catch - finally, catch throws interrupting execution:

  2. try - catch - finally, all throws, catch throwable gets added try exception, which already has finally one bundled in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!