Java接口抛出异常最佳实践

Java接口抛出异常最佳实践,java,exception,interface,Java,Exception,Interface,我正在定义一个新的接口API。。。诚然,我并不是经常这么做。我想定义抛出异常的接口方法,为实现者提供一些灵活性。然后,他们可以选择抛出一个异常,抛出一个更具体的异常子类,或者什么也不抛出。我已经读过好几次了,虽然允许实现类这种灵活性是好的,但是用“throws Exception”定义接口方法也是坏的。相反,建议子类Exception(例如MyException)并抛出子类。对这种做法的解释不够详细,所以有人能详细介绍一下这种最佳做法吗?谢谢。之所以说声明抛出基类异常的接口方法是错误的做法,是因

我正在定义一个新的接口API。。。诚然,我并不是经常这么做。我想定义抛出异常的接口方法,为实现者提供一些灵活性。然后,他们可以选择抛出一个异常,抛出一个更具体的异常子类,或者什么也不抛出。我已经读过好几次了,虽然允许实现类这种灵活性是好的,但是用“throws Exception”定义接口方法也是坏的。相反,建议子类Exception(例如MyException)并抛出子类。对这种做法的解释不够详细,所以有人能详细介绍一下这种最佳做法吗?谢谢。

之所以说声明抛出基类
异常的接口方法是错误的做法,是因为它实际上会使抛出该基类的实例成为接口的合法实现,这显然是您想要避免的

这就是为什么在签名中只使用专用/自定义异常类型的原因

我不想说接口不应该像之前有人在回答中说的那样提前声明抛出任何异常,因为接口实际上不是自由浮动的

作为声明接口的人,您可以以某种方式调用或使用这些方法,并且您可以断言您的代码将如何使用这些方法


事实上,这是您创建的合同和异常是该契约的一部分。事实上,在实现可能存在之前,使用接口的人(而不是实现接口的人)将按照他的工作方式完成。

我更喜欢抛出
RuntimeException的Java标准子类。这提供了允许在不引用API的情况下传播或捕获异常的灵活性

有许多子类可供选择


我经常使用
IllegalStateException
IllegalArgumentException
我很感激尝试给实现者一些灵活性,但是异常是API的一部分,所以你应该考虑一下(选中的)异常有什么意义


通过说
抛出异常
,您并没有帮助接口的客户机理解什么类型的故障会让他们有机会做出适当的反应。可以考虑接受“代码>对象< /代码>的方法参数,以允许实现者决定他们可以接受什么参数。这对实现者来说是件好事,但对接口的客户端来说却是一场噩梦。

最好知道以后需要抛出哪些异常。 有所谓的Liskov替换原则,它建议不要在超类不会抛出的子类中抛出异常

李斯科夫替换原理。按合同设计:

如果您不确定需要抛出哪个异常,请使用“抛出异常”(即使它不酷)。只是在类抛出非您计划的异常时,不要通过实现类来允许意外行为


最糟糕的情况是程序员因为缺少throws声明而拼命抛出运行时异常。

将选中的异常视为可选的返回值。其方法返回
对象
的API是罕见的,可以理解,同样的原则应该适用于检查异常。

通常,抛出异常意味着两种选择之一:

  • 要求打电话的人根据发生的事情采取行动,通常希望他对情况有更广泛/更好的了解,以便做出决定
  • 通知调用方操作失败,无法修复
  • 关注第一种类型引发特定异常是一个好主意,被调用的异常可以:

    try {
    } catch (ServerIsBusyException ex) {
        // wait 10 sec and continue / try another server
    } catch (BadUserNameException ex2) {
       // try another name
    } ....
    
    第二种类型通常是运行时异常,这意味着出现意外情况


    在这篇文章中可以看到一个很好的解释

    您当然不想抛出一个通用异常,这几乎没有任何好处。这有助于提前思考!答案很简单:您负责处理异常(因为您首先允许异常)。因此,请定义您可以处理的异常。您不希望“为实现者提供一些灵活性”。您正在定义他们必须实现的接口。因此,定义它。对于一个因基于意见而被关闭的问题,这是一个非常有用的问题,如上升票数所示。我们需要一种方法让这些问题在SO中存在(并得到意见的回答)。抛出
    RuntimeException
    (因此在方法签名中没有抛出)会阻止实现或客户端预先了解可能发生的问题。您可以在抛出原因中记录运行时异常。问题是你是否想强迫你的用户去处理它。我认为Java社区已经不再在大多数情况下使用检查异常。