我正在尝试将遗留代码库从java1.6迁移到1.7,并且在编译时遇到以下错误:
对create的引用是不明确的,两个方法都创建(long,Object ...) 在Meta和方法中创建(对象...)元数据匹配
这里的Meta是类名。只有在使用JDK1.7进行编译时才会看到此错误。在1.6中它正在构建良好,并且所有依赖项也正常工作。
这两个多态函数如下:
create(long id, Object... paramters) {
....
}
create(Object... paramters) {
....
}
如何解决这个问题,以便代码适用于1.6编译和1.7编译。
编辑:添加引发错误的调用示例:
Id.create(1234);
Id.create(id); // id is a long value
答案 0 :(得分:4)
这是由Java 7编译器中的修复引起的:
<强> Incompatibilities between JDK 7 and JDK 6 强>
区域:工具
概要:大多数特定Varargs方法选择的变化
描述:当多个方法适用于给定的调用站点时,javac编译器中的重载决策算法已经修复了它如何选择最具体的varargs方法(参见JLS,Java SE 7 Edition,第15.12节) .2.5)。
...
虽然javac编译器接受的代码多于JDK 7之前的代码,但在以下情况下,此修补程序还会导致轻微的源代码不兼容:
class Test {
void foo(int... i) {}
void foo(Object... o) {}
void test() {
foo(1,2,3);
}
}
此代码在JDK 6中编译(最具体的方法是foo(int ...))。此代码不在JDK 7下编译。
要使代码在两个JDK中都有效,您需要为编译器提供额外的提示以选择正确的方法,例如
Id.create(1234, new Object[0]);
Id.create(id, new Object[0]);
这将为JDK6和JDK7调用create(long id, Object... parameters)
,并将为varargs部分传递一个大小为0的数组,对于Java 6,也会传递原始代码。
然而,这看起来有点奇怪,我可能会选择(为了更好的可读性)重命名其中一个方法,以便方法调用不依赖于签名。
您还应该考虑Java6处于生命周期结束周期,因此可能另一种选择是修改代码,以便首先与Java7进行编译。
答案 1 :(得分:0)
很长时间被包裹在Long中成为一个物体。
那么编译器如何知道要调用哪个方法?
对于编译器,由于自动装箱,两种方法都匹配方法调用。
如果您为编译器调用create(12)
,则无法确定方法。因为当long被自动装入Long时,它将匹配两种方法。