更改构造函数param类型会破坏另一个jar中的类

Nic*_*olt 3 java parameters binding constructor binary-compatibility

我在一个普通的jar中有以下类:

public class Common 
{
  public Common(List list)
  {
    ...  
  }  
}
Run Code Online (Sandbox Code Playgroud)

然后我将构造函数参数从a更改List为a Collection,如下所示:

public class Common 
{
  public Common(Collection collection)
  {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

重建公共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

}
Run Code Online (Sandbox Code Playgroud)

就像Tom说的那样,正如你在第13行看到的那样,确切的构造函数在编译时被绑定.

你每天学习新的东西 :-)

Tom*_*ine 5

javac确切地解析了在编译时调用哪个方法或构造函数.链接时不会发生这种情况.由于构造函数签名已更改,链接步骤无法找到所请求的方法,因此会引发错误.其中一个需要的-你可以提供给构造修复错误Collection的其他List.稍后Iterable可以添加一个构造函数.

注意,泛型类型不构成签名的一部分,因此可以在保持二进制兼容性的同时更改这些类型.参数和返回类型都是方法签名的一部分(协变返回导致创建合成桥接方法).

JLS中有一个很好的大部分,它确定了构成二进制兼容更改的确切内容.