ソースの互換性とバイナリの互換性には重要な違いがあります。
- あるクラス V1 と V2 の 2 つのバージョンがバイナリ互換である場合、V1 に対してコンパイルされたクラスは V2 に対して問題なく動作することを意味します。
- あるクラス V1 と V2 の 2 つのバージョンがソース互換性がある場合、それは、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);
}