Java为什么在Exception / Throwable类中没有setMessage?

时间:2019-08-27 05:27:42

标签: java exception

我无法理解为什么Java一旦创建便不允许更改Exception类型的异常(或其超类Throwable)的异常消息。它允许使用setStackTrace而不是消息来更改stackTrace。

我觉得用例是真实的,希望能有一些选择。

用例

我有一个控制器服务X,可以调用其他10个依赖服务。为了使调试容易,如果从属服务引发某些异常,我们希望从服务X到其上游浮现一些标识符,以轻松识别失败的请求。为此,我们具有为每个依赖关系创建和设置的requestId。

现在,为了避免所有相关服务之间的重复并简化代码,我们可以创建一个通用的拦截器,使我们能够在每次调用之前和之后进行一些工作。像-

// do some work

requestId = getRequestId(); // create or somehow get requestId
dependentService.setRequestId(requestId);

try {
  dependentService.call();
}
catch (Exception e) {
  e.setMessage(e.getMessage() + ... + requestId);
  throw e;
}

//do some work

但是Java不允许我们设置消息。同时,我们要保留异常及其类型(可以是依赖服务定义的任何自定义类型),所以我不想做类似throw new Exception(e.getMessage() + ...)

的操作。

4 个答案:

答案 0 :(得分:3)

这不是真正的意思,但是您可以在addSuppressed处附加另一个例外:

} catch (Exception e) {
  e.addSuppressed(new ExtraInfoException(...));
  throw e;
}

其中...包含要包含的额外信息。

与添加到异常消息中相比,这样做的优势在于您可以定义ExtraInfoException,以便它在字段中具有所需的信息,而不必从异常消息中解析出来。

话虽如此,一种附加更多异常信息的惯用方式是:

} catch (Exception e) {
  throw new ExtraInfoException(e, ...);
}

具有与您返回结构化信息完全相同的优势,另外的优势是您可以直接捕获ExtraInfoException,而不是捕获Exception,然后反省地寻找额外的信息。< / p>

答案 1 :(得分:3)

  

为什么Java在Exception / Throwable类中没有setMessage?

您的问题的答案是,他们(库设计者)并不认为更改异常消息是一件有用的事情。

在很大程度上 1 ,设计人员认为他们不应该设计API直接支持所有可能的用例...包括几乎没人会遇到的晦涩的用例。 。就像你的 2

在您的情况下,还有其他方法可以实现您想做的事情;查看其他答案。

我快速搜索了Java错误数据库,以查看是否有人将RFE放入请求setMessageThrowable的{​​{1}}方法中。我什么都找不到。如果您的要求稍微常见一点,那么可能会有一个RFE,其中包含拒绝原因的解释。


1-显然,有一些例外,但这不重要。

2-显然,您不同意用例是晦涩的,但这不是重点。问题是为什么他们没有实现这一点,而不是他们是否做错了。 (询问/争论他们是否错是不合时宜的,因为这是见仁见智的。)

答案 2 :(得分:1)

重置消息是某种重写历史记录的方式。捕获异常并处理它们时,您有一个catch块。如果您需要在处理期间引发异常,则这是一个不同的问题,并且异常应该有所不同。

} catch (SomeException e) {
 // here we have SomeException and we want to handle it.
 // if we can't we throw a new one, because we have a problem with handling.
 // if the handling problem cause is SomeException we put it at the cause.
 throw new AnotherException("with some message", e);
}

在堆栈跟踪中,我们将看到由于AnotherException而有了SomeException,这为我们提供了有关问题根源的信息。

答案 3 :(得分:0)

只需像这样抛出新实例:

try {
...
} catch(Exception ex) {
   throw new Exception ("new message", ex);
}