Java-抽象类的二进制兼容性&;子类

Java-抽象类的二进制兼容性&;子类,java,binary-compatibility,Java,Binary Compatibility,在Java中,我定义了一个包含具体方法和抽象方法的抽象类,它必须由第三方开发人员独立地进行子类化。只是想确定一下:我是否可以对抽象类进行任何更改,这些更改与它们的类源代码兼容,但与二进制代码不兼容?换句话说:在他们编译了他们的子类之后,我可以改变抽象类吗?除了向抽象类添加一个抽象方法或者从抽象类中删除一个被子类调用的受保护的方法之外,这些方法当然是源代码不兼容的。这样做可以迫使他们重新编译他们的子类吗?当然可以 您可以意外地使用他们使用过的方法名,现在突然被覆盖,结果可能会截然不同 您可以向类中

在Java中,我定义了一个包含具体方法和抽象方法的抽象类,它必须由第三方开发人员独立地进行子类化。只是想确定一下:我是否可以对抽象类进行任何更改,这些更改与它们的类源代码兼容,但与二进制代码不兼容?换句话说:在他们编译了他们的子类之后,我可以改变抽象类吗?除了向抽象类添加一个抽象方法或者从抽象类中删除一个被子类调用的受保护的方法之外,这些方法当然是源代码不兼容的。这样做可以迫使他们重新编译他们的子类吗?

当然可以

您可以意外地使用他们使用过的方法名,现在突然被覆盖,结果可能会截然不同


您可以向类中添加字段,这些字段会破坏序列化等功能。

如果现在更改系统还不太晚,我建议您这样做。覆盖通常不是定制功能的好方法,因为它非常脆弱。例如,如果以后使用客户机使用过的方法名(客户机现在无意中自动覆盖了该方法名),则覆盖可能会完全破坏类的不变量。提供定制的一种通常更好的方法是为客户机提供一个仅限于定制行为的接口,然后您拥有一个完全具体的类,该类依赖于该接口的实例,并在需要使用定制行为时适当地委托给该接口。这样,您的代码和客户的代码就完全分离了,它们不会相互干扰。

我假设您使用的是技术意义上的“二进制不兼容”;e、 g.类加载器检测到不兼容并拒绝加载类

如果您添加了一个可见方法并声明它为
final
,并且该方法与第三方子类中某个现有方法的签名冲突,则可能会引入二进制不兼容。但是,如果该方法是非最终方法,现有方法将变成对(新)方法的重写,这可能会导致问题。。。但不是二进制不兼容

同样,添加新的可见字段将导致隐藏,可能导致混乱的行为,并将破坏对象序列化。但这不会导致二进制不兼容

一般来说,这意味着需要考虑应用程序的语义问题以及简单的二进制兼容性。Java类型系统在这方面也帮不了你

为了完整性,您可以在代码中做一些其他事情,以破坏第三方类的二进制兼容性:

  • 降低抽象类和/或其方法的可见性
  • 更改用作参数结果和异常类型的其他类的签名
  • 更改抽象类扩展的超类链,或在这些类中进行不兼容的更改,或
  • 更改抽象类实现的接口树,或在这些接口中进行不兼容的更改

感谢您提供了全面的答案,感谢您思考了我也想到但没有描述的内容,即打破实施者代码的任何其他方法。回答得好。二进制和源代码兼容性的规则彼此非常独立。将两者分开理解是很重要的。感谢您也提供了替代方案!这也是我所考虑的——我在权衡其复杂性的成本(维护对实现的引用并委托给它),但由于这种可插入架构是一种需求,我将这样做。