java更改构造函数参数类型会中断另一个jar中的类
我在一个公共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行看到的,确切的构造函数是在编译时绑定的
你每天都会学到新东西:-)
# 1 楼答案
javac精确地解析在编译时调用哪个方法或构造函数。这不会在链接时发生。由于构造函数签名已更改,链接步骤无法找到请求的方法,因此会抛出错误。您可以通过向构造函数提供一个
Collection
和另一个List
来修复错误。稍后可以添加一个采用Iterable
的构造函数注意,泛型类型不构成签名的一部分,因此可以在保持二进制兼容性的同时更改这些类型。参数和返回类型都构成方法签名的一部分(协变返回导致创建合成桥方法)
有一个nice big section in the JLS精确定义了什么构成二进制兼容更改
# 2 楼答案
我认为这可能是图书馆版本的问题。您确定在同一上下文中的其他地方没有其他版本的commons库吗