【问题标题】:Generic way to add info to a Throwable without creating a new Throwable在不创建新 Throwable 的情况下向 Throwable 添加信息的通用方法
【发布时间】:2008-11-19 16:40:25
【问题描述】:

在不创建新 Throwable 的情况下添加通用方式来向 Throwable 添加信息是否有益?

我经常看到这样的代码:

try {
    foo();
} catch (Exception e) {
    throw new Exception(e.getMessage() + " extra info=" + blah, e);
}

添加Throwable.setProperty(String key, String value)这样会不会更好,这样上面的代码就变成了下面的样子?

try {
    foo();
} catch(Exception e) {
    e.setProperty("extra info", blah);
    throw e;
}

额外的信息可以在消息和堆栈列表之间打印(每行一个)。

好处: 1. 不需要创建新的Throwables 只是为了添加额外的信息。 2.堆栈跟踪不会有多层原因跟踪 (因此更容易阅读) 3. 减少创建额外堆栈跟踪的成本。

【问题讨论】:

  • 如果您担心 Throwable.fillInStackTrace() 的成本,那么我敢说您做错了:)(假设您对“成本”的定义与 CPU 周期有关。)
  • 我不担心新的 Throwable 会占用大量 CPU ——但即使移除少量浪费的 CPU 也是有益的。

标签: java exception


【解决方案1】:

链式异常已经负责删除冗余堆栈帧。也就是说,您只会看到一个给定的堆栈帧列出一次。这是一个见仁见智的问题,但我认为缺少链式异常是一个缺点。

不鼓励扩展RuntimeException 会很好。这可能在这方面有所帮助。

中间的堆栈帧可能希望在堆栈展开时添加自己的上下文。这可能导致财产损失。应该有一种机制来处理这个问题,例如给定属性名称的一堆值。

这在核心 Java 中永远不会发生,但没有什么能阻止您为自己的异常类使用此约定。

【讨论】:

  • 这不会删除链式异常——当您不想更改 Throwable 类时,只需添加一个替代方案。 Clobbering:也许字符串行列表更好。
【解决方案2】:

像往常一样,有例外,它非常依赖于场景。尽管您应该尝试明确您要捕获的异常,但您还希望明确说明当前范围内异常的原因,而不是增加从另一个范围抛出的异常。如果您没有要添加的内容可以帮助调用者并且无法执行某些操作来响应特定异常,请让它传播。如果您的范围内有与调用者相关的信息,请使用您的信息抛出异常,并链接到捕获的异常。这里的关键是范围。始终从当前范围生成结果并允许其他范围执行相同操作。

【讨论】:

    【解决方案3】:

    总的来说,我认为在这种情况下使用标准成语会更好。在这种情况下,标准的习惯用法是包装异常,如下所示:

    try {
      foo();
    } catch (Exception e) {
      throw new MySpecificException("extra info=" + blah, e);
    }
    

    此外,通常最好不要捕获通用异常。如果您想捕获并向 RuntimeException 添加信息,请执行此操作,并创建一个新的 RuntimeException。否则,请仔细考虑要捕获和抛出哪些已检查异常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多