2

我想创建两个函数,比如说

long min(long...);
int min(int...);

但是当我尝试调用第二个 ie 时,min(1, 5)我得到了模棱两可的方法调用

除了重命名还有其他解决方法吗?

4

4 回答 4

6

这是一个已知的错误

您描述的行为是 Java 7 已修复的错误。请参阅发行说明中的​​详细信息,名为“更改最具体的 Varargs 方法选择”部分。

它应该编译的原因

在确定最具体的方法时,可变参数排在最后。在JLS 15.12.2.4中定义了用于确定当有多个 vararg 方法适用的规则- 这是一个摘录:

如果满足以下任一条件,一个名为 m 的变量 arity 成员方法比另一个同名的变量 arity 成员方法更具体:
- [...]
- 一个成员方法有 k 个参数,而另一个成员方法有 n 个参数,其中 n ≥ k,并且:

  • 第一种方法的参数类型为U1, ..., Uk-1, Uk[]。
  • 其他方法的参数类型为T1, ..., Tn-1, Tn[]。
  • 对于从 1 到 n 的所有 j,Uj <: Tj

在您的情况下,k = n,U1[] = int[]因此T1[] = long[]可以确定是否int <: long或相反。

换句话说,考虑的类型不是int[]vs.long[]而是intvs. long碰巧应该选择int <: longint...方法并且应该编译它。

结论:

该代码应该(并且确实)可以使用 Java 7 编译,但不能使用 Java 5 或 6 编译。下面的代码int使用 Java 7 打印:

public class Test1 {
    public static void main(String[] args) {
        new Test1().m(1, 2);
    }
    int m(int... i) {
        System.out.println("int");
        return 0;
    }
    long m(long... i) {
        System.out.println("long");
        return 0;
    }
}
于 2012-11-23T07:04:02.413 回答
1

问题是当您使用 调用这些方法时integer没有任何方法提供与您使用的参数完全匹配的参数。此外,两者都可以将用逗号分隔的值作为参数。因此错误。var-argsvar-argsintambiguous method

当你调用重载方法时,Compiler选择第exact match一个。然后nearest type投。

现在,由于var-args只是一个array,编译器在传递值时无法决定使用哪个数组integer。因为,这两个数组都不能被视为exact matchnearest conversion。因此,它需要两种方法都可以调用。

关于. method invocation_ Overloading您可以从Java Language Specification.


正如@assylias 的回答一样,这个问题已在 Java 7 中得到修复。但它不适用于 Java 版本 < 7。

于 2012-11-23T06:40:49.397 回答
1

试试这个

public class Test {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        new Test().m(100L,512L);
        new Test().m(100,512);
    }

    int m(int... i) {
        System.out.println("int");
        return 0;
    }

    long m(long... i) {
        System.out.println("long");
        return 0;
    }
}
于 2012-11-23T09:24:58.563 回答
0

这些方法签名是唯一的,并且是有效的方法重载。

问题必须出在方法调用参数中。我的猜测是您正在使用文字调用该方法,例如:

min(100) 

它不喜欢这样,因为 100 是一个整数文字,但它会自动转换为长整数。

通过在长文字末尾使用 L 来消除方法调用的歧义应该可以解决问题:

min(100L)

此外,您可以使用 Java Object Integer 和 Long 来显式调用,并让自动装箱处理到原始类型的转换:

min(new Long(100))
min(new Integer(100))
于 2012-11-23T06:37:46.857 回答