我试图弄清楚为什么我的两个Java库难以一起玩。这是场景:
库1有一个带有以下构造函数的类A:
public A(Object obj) { /* boilerplate */ }
在以前的版本中,A的构造函数是:
public A(Serializable s) { /* more or less same boilerplate */ }
现在,库2是针对先前版本构建的,并构造了A:
的实例A myObject = new A( (Serializable) arg);
当库1(最新版本)和2一起部署时,构造函数调用抛出NoSuchMethodError,并且堆栈跟踪解释了JVM正在寻找具有Serializable参数的构造函数。
在我看来,所有对象实例都可以转换为Object,即使在调用期间显式转换为接口也是如此。然而,这个实验已经证实了。对于后代,任何人都可以详细说明Java的哪些规则导致NoSuchMethodError出现?我非常感谢规范引用。
答案 0 :(得分:6)
编译库2时解析new A(...)
调用的方法,并将其签名存储在库2的类文件中。
如果针对旧版本的库1编译库2,A myObject = new A( (Serializable) arg)
的字节码应如下所示:
9: new #1; //class A
12: aload_1 //arg
13: invokespecial #24; //Method "<init>":(Ljava/io/Serializable;)V
如果调用此代码时不再存在带有此签名的方法,则会得到NoSuchMethodError
。
答案 1 :(得分:1)
构造函数在编译时被重载(未被覆盖)并受限制。
所以lib2正在寻找A(Serializable),但只有A(对象)。