【问题标题】:Refactored methods and binary compatibility in JavaJava 中重构的方法和二进制兼容性
【发布时间】:2010-11-24 19:46:34
【问题描述】:

在重构方法时,很容易在 Java 中引入二进制不兼容(与以前版本的代码)。

考虑更改方法以将其参数类型扩展为父接口:

 void doSomething(String x);

 // change it to

 void doSomething(CharSequence c);

使用此方法的所有代码都将继续编译而无需更改,但确实需要重新编译(因为旧的二进制文件将因 MethodNotFoundError 而失败)。

如何将方法拉到父类中。这需要重新编译吗?

// before
public class B extends A{
    protected void x(){};
}

// after
public class A {
    public void x(){};
}
public class B extends A{}

该方法已从 B 移至父 A。它还将可见性从受保护更改为公开(但这不是问题)。

我是否需要在 B 中维护一个“二进制兼容性包装器”,还是它会继续工作(自动分派给父类)?

 // do I need this ?
 public class B extends A{
     // binary compatibility wrapper
     public void x(){ super.x(); }
 }

【问题讨论】:

    标签: java refactoring binary-compatibility


    【解决方案1】:

    它应该继续自动工作,因为 Java 具有动态链接

    【讨论】:

    • 我对扩展的方法也有同样的想法......这不起作用,因为参数的类名成为内部方法名的一部分。我想知道编译器认为声明方法的类的名称是否也是如此。
    • “加宽”会影响方法的签名,但将方法移动到超类不会。在命令行上尝试一下。
    • 在 JLS 中有二进制兼容性的细节。
    【解决方案2】:

    “加宽”会影响方法的签名,因此不兼容二进制。将方法移动到超类不会影响方法签名,因此它会起作用。 Eclipse 有一个很棒的文档来描述 API 和 ABI 的兼容性:

    http://wiki.eclipse.org/Evolving_Java-based_APIs

    更明确的规则在第 2 部分:

    http://wiki.eclipse.org/Evolving_Java-based_APIs_2

    我相信您对“更改形式参数的类型”(即您所说的扩大)或“将 API 方法向上移动类型层次结构”(即您所说的拉入父类)感兴趣)。

    【讨论】:

      猜你喜欢
      • 2013-02-05
      • 2011-02-19
      • 1970-01-01
      • 2015-10-11
      • 2011-08-03
      • 1970-01-01
      • 2011-08-09
      • 2016-08-08
      • 1970-01-01
      相关资源
      最近更新 更多