Iている以下のクラス:同じイレーズバイナリを持つリターンタイプジェネリックは互換性がありますか?
public abstract Foo {
Foo() {}
public abstract Foo doSomething();
public static Foo create() {
return new SomePrivateSubclassOfFoo();
}
}
が、私は次の定義にそれを変更したい:この変更は、バイナリ互換性
public abstract Foo<T extends Foo<T>> {
Foo() {}
public abstract T doSomething();
public static Foo<?> create() {
return new SomePrivateSubclassOfFoo();
}
}
ですか? つまり、reocmpilationせずにクラスの古いバージョンに対してコンパイルされたコードは新しいバージョンで動作しますか?
私はSomePrivateSubclassOfFoo
を変更する必要があることを知っていますが、これは問題ありません。また、古いクライアントコードがコンパイルされたときに、この変更によって生のタイプに関する警告が表示されることもわかります。私は、古いクライアントコードを再コンパイルする必要がないことを確認したいだけです。
T
の消去がFoo
であり、したがって、バイトコード内のdoSomething
の署名が以前と同じであるため、これは問題ありません。 javap -s
で印刷された内部型署名を見ると、確かにこれが確認されています(-s
を付けずに印刷された「非内部型」署名は異なります)。 私もこれをテストし、それは私のために働いた。
しかし、Java API Compliance Checkerは、2つのバージョンがバイナリ互換ではないことを示しています。
だから何が正しいですか? JLSはここでバイナリ互換性を保証していますか、私のテストでは幸運でしたか? (なぜこれが起こるのでしょうか)