【问题标题】:Java - binary compatibility of abstract class & subclassesJava - 抽象类和子类的二进制兼容性
【发布时间】:2011-02-19 17:51:21
【问题描述】:

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

【问题讨论】:

    标签: java binary-compatibility


    【解决方案1】:

    当然。

    您可能不小心使用了他们曾经使用过的方法名称,现在突然被覆盖,结果可能截然不同。

    您可以将字段添加到混淆序列化等的类中。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 感谢您提供替代方案!这也是我正在考虑的 - 我正在权衡它的复杂性成本(维护对实现的引用并委托给它),但由于这种可插拔架构是一项要求,我会这样做。
      【解决方案3】:

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

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

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

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

      为了完整起见,您可以在代码中执行其他一些操作,这些操作会破坏 3rd 方类的二进制兼容性:

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

      【讨论】:

      • 感谢您提供全面的答案,并考虑到我也想到但未描述的内容,即任何其他破坏实施者代码的方法。
      • 好答案。二进制和源代码兼容性的规则彼此非常独立。分开理解它们很重要。 motlin.com/2010/binary-and-source-backwards-compatibility
      猜你喜欢
      • 2012-03-04
      • 2010-11-24
      • 1970-01-01
      • 2015-10-11
      • 2013-02-05
      • 2011-08-03
      • 1970-01-01
      • 1970-01-01
      • 2011-08-09
      相关资源
      最近更新 更多