3

我正在尝试将遗留代码库从 java1.6 迁移到 1.7,并且在编译时出现以下错误:

对 create 的引用不明确,Meta 中的方法 create(long,Object...) 和 Meta 中的方法 create(Object...) 都匹配

这里 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
4

2 回答 2

4

这是由 Java 7 编译器中的修复引起的:

JDK 7 和 JDK 6 之间的不兼容性

领域:工具

概要:最具体的 Varargs 方法选择的变化

描述:javac 编译器中的重载解析算法已修复,当有多个方法适用于给定调用站点时,它如何选择最具体的可变参数方法(请参阅 JLS,Java SE 7 版,第 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]);

这将为create(long id, Object... parameters)JDK6 和 JDK7 调用 ,并将为可变参数部分传递一个大小为 0 的数组,在 Java 6 的情况下也会传递原始代码。

尽管如此,这看起来有点奇怪,我可能会选择(为了更好的可读性)重命名其中一个方法,以便方法调用不依赖于签名。

您还应该考虑到 Java6 正处于其生命周期结束时,因此可能另一种选择是修改代码,使其首先可以与 Java7 一起编译。

于 2013-04-05T09:56:59.713 回答
0

当包裹在 Long 中时 long 成为一个对象。

那么编译器如何知道调用哪个方法呢?

对于编译器,由于自动装箱,这两种方法都与方法调用匹配。

如果您调用create(12)编译器,则无法决定方法。因为当 long 自动装箱为 Long 时,它将匹配这两种方法。

于 2013-04-05T09:47:40.670 回答