更改构造函数param类型会破坏另一个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
?
我认为这可能是库版本的问题。您确定在同一上下文中的其他地方没有其他版本的公共库吗?
不隶属于 StackOverflow