源代码兼容性和二进制兼容性之间有一个重要区别。
- 如果某个类 V1 和 V2 的两个版本是二进制兼容的,这意味着针对 V1 编译的类在 V2 上运行得很好。
- 如果某个类 V1 和 V2 的两个版本是源代码兼容的,这意味着可以针对 V1 编译的类将针对 V2 编译得很好。
正如您所经历的那样,源代码兼容性并不自动意味着二进制兼容性。
编译源代码时,要调用的具体方法签名由编译器决定并存储在.class
文件中(在本例中为doSomething(List)
)。
如果更改了类并在添加时doSomething(List)
删除了方法doSomething(Collection)
,则保留了源代码兼容性(因为您可以简单地针对新类编译相同的代码),但二进制兼容性会丢失!
Java 语言规范有一整节是关于二进制兼容性的。
总结一下:虽然将方法的参数类型更改为更通用的类型(通常)是源兼容的,但它不是二进制兼容的。
如果要保留二进制兼容性,则更改必须如下所示:
public void doSomething(Collection foo) { ... } // original method with changed argument type
public void doSomething(List foo) { // new binary compatibility method, just delegates to original one
doSomething((Collection) foo);
}