Java API中断

Java API中断,java,backwards-compatibility,Java,Backwards Compatibility,我有以下API: public interface MyApi { /** * Performs some stuff. * @throws MyException if condition C1 */ public void method() throws MyException; } 我现在正在API实现中执行以下修改 public class MyApiImpl { public void method() throws MyExceptio

我有以下API:

public interface MyApi {

   /**
    * Performs some stuff.
    * @throws MyException if condition C1
    */
   public void method() throws MyException;
}
我现在正在API实现中执行以下修改

public class MyApiImpl {

   public void method() throws MyException {
     if (C1) {
       throw new MyException("c1 message");
     }
     ...
   }
}
替换为:

public class MyApiImpl {

   public void method() throws MyException {
     if (C1) {
        throw new MyException("c1 message");
     } else if (c2) {
        throw new MyException("c2 message");
     }
     ...
   }
}
你认为这是一个API破坏吗?

客户机的代码仍将编译,但API javadoc定义的方法契约不再受尊重,因为MyExceptan是由“新”条件抛出的

如果只更新了我的API jar文件,客户端应用程序仍然可以工作,但根据客户端捕获异常的方式,应用程序的行为可能会发生很大的变化


您对此有什么看法?

我的观点是,您不应该更改文档中API定义的合同。如果您需要新的行为,您应该a.)创建一个新的方法,该方法可以由反映此新行为的客户端调用,或者b.)与客户端讨论更改的需要,并让他们知道


这实际上是双向的,这是你和你的客户之间关于你的方法的问题。

是的,当C1没有发生时,你抛出了一个异常,这破坏了接口的契约


根据经验,接口契约越含糊,就越容易不被打破:)如果接口不是用明确的C1定义的,而是用更一般的术语定义的,这就提供了更多的灵活性。

这在很大程度上取决于c2是什么。是否在现有合同的逻辑范围内?如果是这样的话,你抛出MyException就是在满足合同。如果不是,那么您可能需要抛出一种新类型的异常

我应该指出,我不太喜欢检查异常。最终,强迫某人处理异常并不一定会使他们的代码变得更好或更安全(事实上,这会产生相反的效果,因为他们会草率地吞下虚假的异常)。

我会说“不”,没有API破坏,除非MyException是RuntimeException。那就是

不管怎样,我要为条件C2的MyException子类


条件C1和C2都应该是“异常的”,我不会养成抛出异常的习惯,这是一种破坏。API是由语言构造强制执行还是简单地记录是无关紧要的


这种破坏是否会导致客户端代码出现问题则是另一个问题。可能是您正在修复缺陷,需要以这种方式覆盖案例C2以修复缺陷。从这一点来看,客户机代码开发人员可能会很高兴您做出了这一更改(假设他们目前没有以一种会在更改面前崩溃的方式解决缺陷!)

我认为这里的问题是您将接口的一部分、实现特定的条件。如果“C1”条件只是实现的一部分,那么您可以简单地创建一个新的实现,在不破坏接口的情况下对“C1”或“C2”抛出异常