【问题标题】:Can exception masking be completely prevented with try-with-resources statement使用 try-with-resources 语句可以完全防止异常屏蔽吗
【发布时间】:2018-11-05 05:56:17
【问题描述】:

我知道引入 try-with-resources 语句是为了解决(或)防止异常屏蔽。

考虑以下代码:

class TestExceptionSuppressing {
    public static void main(String[] args) {
        try {
            testMethod();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            for (Throwable t : e.getSuppressed()) {
                System.err.println("Suppressed Exceptions List: " + t);
            }
        }
    }

    static void testMethod() {
        try (InnerClass inner = new InnerClass()) {
            throw new IOException("Exception thrown within try block");
        } catch (Exception e) {
            throw new RuntimeException(
                    "Exception thrown within catch block.Hence exception thrown within try block will be lost (or) masked");
        }
    }

    static class InnerClass implements AutoCloseable {

        @Override
        public void close() throws Exception {
            throw new Exception("Exception thrown in close method will be tacked on to existing exceptions");
        }
    }
}

输出:在 catch 块中抛出异常。因此在 try 块中抛出的异常将丢失(或)被屏蔽

显然,testMethod() 的 catch 块中抛出的异常已经掩盖了 try 块中抛出的 io 异常以及被抑制并添加到此 io 异常中的异常(在 close 方法中抛出)

此代码示例可能证明 try-with-resources 可能无法完全防止异常屏蔽。

我知道这里的情况很混乱,可能会让人感到困惑,但有可能发生这种情况。 我的问题是,有没有办法防止这种情况发生,即即使使用 try-with-resources 语句仍然会发生异常屏蔽?

【问题讨论】:

  • 这是与 try with resource 同时引入的更改,但是一个普通的 try/finally 块允许您查看被抑制的异常。

标签: java exception try-with-resources


【解决方案1】:

使用RuntimeException(String, Throwable)可以保留原来的异常

使用指定的详细消息和原因构造一个新的运行时异常。

throw new RuntimeException(
                "Exception thrown within catch block  won't be lost (or) masked", e);

如果你想添加抑制的尝试和资源异常,你需要使用addSuppressed(Throwable)方法,在你的情况下:

RuntimeException runtimeException = new RuntimeException(
                    "Exception thrown within try block won't be lost (or) masked", e);
            runtimeException.addSuppressed(e.getSuppressed()[0]);

更多信息Suppressed Exceptions and Try With Resources

但是,仅仅因为 CloseException 在这种情况下被抑制,并不意味着这个被抑制的异常被忽略了。为了解决这种抑制异常的概念,Java 7 中的 java.lang.Throwable 类中添加了两个新方法和一个构造函数。

public final void addSuppressed(Throwable exception)

【讨论】:

  • 这几乎也适用于所有异常,而不仅仅是 RuntimeException。稍后您可以使用 getCause() 检索包装的异常。
  • @Thilo 您通常是对的,但我看到(主要是自定义的)异常类型忘记添加它选项
  • @user7294900 - 你说在 try-with-resourced 语句的关联块中抛出的异常不会被这种方法掩盖。您指定的有关 catch 块中引发的异常的消息不会丢失。我认为这是一个拼写错误。不是吗?另外,我们是否也可以以这种方式指定已检查的异常,以使原始异常不丢失?
  • @sake add to my answer 添加在 try-with-resourced 语句的关联块中引发的异常
  • @user7294900 - 我相信通过这种方法(即在构造一个 throwable 时提供原因并在 catch 块中为构造的 throwable 添加抑制的期望),我们可能会在 try 中得到(否则)被屏蔽的异常-with-reosurces 语句是 catch 块中异常的原因,但正如我在问题中提到的,异常屏蔽仍然可以通过 try-with-resources 语句发生,并且无法完全防止。你同意吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 2014-05-21
  • 1970-01-01
相关资源
最近更新 更多