谁决定哪些异常被抑制?

3
据我理解,Java 7的异常抑制功能是自动的。换句话说,在6中发生在finally块中的异常会自动被压制,以便将资源分配过程中发生的异常置于优先位置。
因此,在这个例子中,可能会出现以下问题:a)打开资源时出错;b)关闭资源时出错;或c)两者皆有可能出错。
据我理解,Java 7会抛出在打开资源时发生的异常,并询问我们需要哪些在其他地方发生的被压制的异常。
    try (BufferedReader inputReader = Files
            .newBufferedReader(Paths.get(new URI(
                    "file:///Users/me/Desktop/readme.txt")), Charset
                    .defaultCharset())) {
        String inputLine;
        while ((inputLine = inputReader.readLine()) != null) {
            System.out.println(inputLine);
        }
    } 

问题是,程序员能决定哪些内容被抑制吗?毕竟,public addSuppressed()是存在的。
请提供一个示例和使用情况。
2个回答

4
这不是随意的——被抑制的异常是那些本来会掩盖导致 try 块失败的主要异常,而这些异常在 finally 块中。该功能确保您获得整个结构中抛出的所有异常,但您捕获的将是更重要的异常。
您无法选择哪些异常被抑制。该方法肯定存在,否则整个过程就无法工作。如果您愿意,可以编写自己的异常处理代码并随意使用 addSuppressed

那么,“public”方法“addSuppressed()”不应该被使用吗? - James Raitsev
1
无论何时您认为它会对您有益,请务必使用它。我的“你不能选择被压制的内容”是指ARM块。 - Marko Topolnik

0
为什么需要新的回复:
  1. 更多澄清(至少我曾经阅读时需要,特别是在 catch 方面)
  2. 添加代码
  3. 添加了使用案例 / 示例以说明 addSuppressed 的用法(catch

逐个案例:

  1. 旧的 try-catch-finally(或 try-finally)将抑制除 finally 块以外的所有异常。此外,如果您触及它,无论是否抑制了某些内容,都不会在抑制异常列表中。
  2. try-with-resources-finally 将传播 try 异常,并将 finally 异常添加到抑制列表中。
  3. try-...-catch-finally 的工作方式类似。如果 catch 抛出异常,则会抑制 try 异常,使其丢失,除非您在 catch 异常上手动使用 addSupressed()(将原始异常绑定到新抛出的异常)。我认为这是接受答案在最后一段涵盖的情况。

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");
    }
}

}

所以,你不能选择被抑制的内容,而addSuppressed是为了使堆栈跟踪更完整。

输出:

  1. try-catch-finally,catch抛出中断执行:
    catch throws, no suppression info

  2. try-catch-finally,所有抛出异常都会被添加到try异常中,其中已经包含了finally中的异常

catch repacked, suppression info added by hand


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接