如何管理API中的异常?

时间:2011-09-04 19:43:49

标签: java api exception

好的,当我编写任何API时,我总是有这个疑问,a.k.a。,代码可重用。

您如何处理例外情况?有不同的可能性:

  • 始终将它们投放到客户端。异常是累积的,因此如果方法A使用私有方法B并且方法B抛出异常并且方法A抛出另一个异常,则客户端看到2个异常并且只应该看到最新的因为他正在调用的方法。我们可以积累很多例外。

  • 仅抛出客户端调用的方法产生的异常。我们如何处理内部异常?只需打印例外(printStackTrace())?将此已检查的异常转换为未确认的异常,因此我们只需抛出它们吗?

  • 实现客户端可用于设置其首选日志的界面。我只是拒绝这样做。

  • 扩展RuntimeException并始终抛出自定义的未经检查的异常。发布到客户端的所有方法都得到了很好的解释,并说如果合同,方法可以抛出异常实现了。我喜欢这种技巧。

3 个答案:

答案 0 :(得分:2)

关于您的第一点 - 最好为您的API创建特定于域的异常层次结构(例如spring's DataAccessExceptions)并将所有内容包装到您的客户端。

关于已检查/未检查的例外的经验法则是:

  • 当客户端无法对错误采取任何措施时,抛出未经检查的异常
  • 当客户端应该处理错误时检查异常

关于第二点 - 如果内部错误以任何方式影响客户端,则永远不要隐藏它们。此外,请勿将错误信息输出到客户端可能不知道的辅助通道(如e.printStackTrace())中。如果您需要向用户提供非特殊信息,您有两种选择:

  1. 提供接受某种Logger的方法
    • 优点:明确,没有其他依赖
    • 缺点:混乱API,使用起来很麻烦
  2. 使用SLF4J日志记录外观并以正常方式进行日志记录
    • 优点:保持API清洁
    • 缺点:依赖于slf4j-api

答案 1 :(得分:1)

您应该在他们调用的方法上将异常抛回客户端。私有方法在API内部生成的异常应该将异常抛回客户端或捕获它并执行一些有用的操作。如果在生成异常时无法继续执行,则应该在方法堆栈中抛出异常。

通常我喜欢通过扩展Exception或它的子类来使用异常。因此,抛出的异常类型更有意义,更容易被客户理解。所以我经常抓住然后抛出自定义的那个。

通常可以通过扩展Exception来最好地使用已检查的例外情况。它们通常更容易调试。但是,在某些情况下,您可能希望使用未经检查的例外。

无论你做什么都不使用返回值来表示特殊情况,这对Java来说是不好的做法。我以为我之前已经看过它了。

无论您何时抛出异常,都要确保向客户端添加有意义的消息,客户可以理解。

它最终归结为您在API中所需的内容,但您应该始终使其易于使用,并在发生异常时轻松进行调试。

答案 2 :(得分:0)

我不确定这是否属于您的第一项,但我最喜欢的是在内部捕获异常,然后抛出一个新的特定异常,原始异常为根本原因:

class A {
  void methodA() throws AException { /*...*/ }
}

class B {
  void methodB() throws BException {
    try {
      new A().methodA();
    } catch(AException e) {
      throw new BException("A problem occured in methodA", e);
    }
  }
}

这当然可以导致几个级别的嵌套异常,但优点是更好的信息隐藏(因为你不必通过它们抛出的异常来暴露内部使用的方法),而且接口的混乱也少得多,如你不会在你的投掷声明中得到20个例外。