コンストラクターのパラメーターの型を変更すると、別の jar のクラスが壊れる
-
05-07-2019 - |
質問
一般的な jar に次のクラスがあります。
public class Common
{
public Common(List list)
{
...
}
}
次に、コンストラクターのパラメーターを List
に Collection
次のように:
public class Common
{
public Common(Collection collection)
{
...
}
}
共通の jar を再構築してシステムを実行すると、 NoSuchMethodError
コンストラクターを呼び出すとき、そのクラスを再コンパイルするまで、依存クラスで。
コンストラクターが依存クラスのバイトコードにどのようにバインドされているかに沿って、何が原因であるかについていくつかの考えがありますが、100%確信はありません。
誰かここで何が起こっているのかを解明してもらえませんか?
アップデート
その後、簡単なテストを行ってバイトコードを調べました。
Compiled from "Client.java"
public class Client extends java.lang.Object{
public Client();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2; //class ArrayList
3: dup
4: invokespecial #3; //Method java/util/ArrayList."<init>":()V
7: astore_1
8: new #4; //class Common
11: dup
12: aload_1
13: invokespecial #5; //Method Common."<init>":(Ljava/util/List;)V
16: pop
17: return
}
Tom が言ったように、13 行目に見られるように、正確なコンストラクターはコンパイル時にバインドされます。
毎日何か新しいことを学びます:-)
解決
javac は、コンパイル時に呼び出すメソッドまたはコンストラクターを正確に解決します。これはリンク時には発生しません。コンストラクターのシグネチャが変更されたため、リンク ステップでは要求されたメソッドを見つけることができないため、エラーがスローされます。コンストラクターに提供することでエラーを修正できます。 Collection
もう一方の List
. 。その後、コンストラクターが Iterable
を追加することができます。
ジェネリック型は署名の一部を形成しないため、バイナリ互換性を維持しながら変更できることに注意してください。パラメーターと戻り値の型はどちらもメソッドのシグネチャの一部を形成します (共変戻り値により合成ブリッジ メソッドが作成されます)。
があります JLSの素晴らしい大きなセクション バイナリ互換性のある変更を構成するものを正確に定義します。
他のヒント
正しいListクラスとCollectionクラスをインポートしていますか?つまり、 java.util.List
および java.util.Collection
?
ライブラリのバージョンに問題があると思います。同じコンテキストの他の場所にcommonsライブラリの別のバージョンがないことを確認しますか?