Es gibt ein Jar, das, wenn es erstellt wurde, eine Methode MyClass.doSomething(List)
verwenden sollte. Diese Methode wurde in doSomething(Collection)
geändert und in ein anderes jar (nur mit dieser Klasse) eingefügt.
Ich lege mein zweites Glas vor mein erstes Glas im Klassenpfad, aber wenn der Code in meinem ersten Glas MyClass.doSomething()
mit einer Liste aufruft, bekomme ich immer noch ein
java.lang.NoSuchMethodError: MyClass.doSomething(Ljava/util/List;)Ljava/util/List;
Wie ist das möglich? Ant wurde verwendet, um die Gläser zu kompilieren.
Es gibt einen wichtigen Unterschied zwischen Quellkompatibilität und Binärkompatibilität.
Bei der Quellkompatibilität bedeutet nicht automatisch die Binärkompatibilität, wie Sie bereits festgestellt haben.
Wenn die Quelle kompiliert wird, wird die spezifische Methodensignatur, die aufgerufen werden soll, vom Compiler entschieden und in der Datei .class
gespeichert (in diesem Fall ist es doSomething(List)
).
Wenn die Klasse geändert wird und die Methode doSomething(List)
entfernt wird, während doSomething(Collection)
hinzugefügt wird, wird die Quellkompatibilität beibehalten (weil Sie einfach denselben Code für die neue Klasse kompilieren können), aber die Binärkompatibilität ist verloren!
Die Java-Sprachspezifikation enthält einen vollständigen Abschnitt zur Binärkompatibilität .
Zusammenfassend: Während das Ändern des Argumenttyps einer Methode auf einen allgemeineren Typ (normalerweise) quellkompatibel ist, ist es nicht binärkompatibel.
Wenn Sie die Binärkompatibilität beibehalten möchten, müsste die Änderung wie folgt aussehen:
%Vor% Wenn Sie NoSuchMethodError
erhalten, heißt das im Allgemeinen, dass die zur Laufzeit verwendete Version der Zielklasse sich von der Version der Zielklasse unterscheidet, für die die aufrufende Klasse kompiliert wurde. In Ihrem Fall ist es kein überraschender Fehler; Der Bytecode in der ersten JAR wird weiterhin gegen das Vorhandensein einer Methode kompiliert, die ein List
, das nicht existiert , verwendet.
Dies könnte auf die inkrementelle Kompilierung von Ant zurückzuführen sein, die nicht bemerkt, dass sich abhängige Klassen geändert haben, oder etwas ähnliches.
Wenn Sie eine saubere Wiederherstellung des gesamten Projekts durchführen (zumindest die von Ihnen erwähnten JARs), sollte dieses Problem gelöst werden, da der Compiler Bytecode erstellt, der die neue doSomething
Signatur aufruft.
Tags und Links java nosuchmethoderror signature