方法重载 - 引用是模糊的

时间:2014-09-24 20:12:35

标签: java overloading

我试图更好地掌握功能重载。

我是这个测试程序(原谅我的C启发Java)。

public class Test {
    static void f(int x, double y)
    {
        System.out.printf("%d, %f",x,y);
    }

    static void f(double x, int y)
    {
        System.out.printf("%f, %d", x, y);
    }


    public static void main(String args[]) {

    f(1, 2);

    }
}

现在,如果我打电话,

f(1, 2);

存在编译器错误*reference to f is ambiguous*

为什么会出现这个错误?我们不打电话给f(int, int)吗?但是没有声明这样的方法。我期待"找不到适合f"相反,但我没有得到一个,为什么?

3 个答案:

答案 0 :(得分:12)

int在所有这些语言中都可转换为double,因此如果只有一个可用,则很容易:转换需要转换的值到double,然后调用方法。

但是在这种情况下,两个方法都是“有效的”,因为每个方法都可以自己处理 - 但两者都不比另一个“更好”,因为在每种情况下,一个参数只需要身份intint转换,另一个需要intdouble转换。因此,在Java和C#中,它都是模糊的,并且会因编译时错误而失败。我想象这也是它在C ++中的作用,但我不确定。在Java和C#中,如果您还有 方法static void f(int x, int y),那么对于该方法调用,这将明显优于其他两个方法。

如有疑问,请参阅相关语言规范。对于Java,JLS section 15.12是相关部分。在C# 5 specification中,它是7.5节。

答案 1 :(得分:1)

你有这些函数非常接近彼此或更好的感觉模糊不清让编译器理解,所以编译器会因为看到这些而感到困惑

static void f(int x, double y)

static void f(double x, int y)

为了摆脱编译器的这种混乱或歧义,可以简单地添加以下内容

 static void f(int x, int y)

我认为此评论更适合您解释

  

问题不在于缺少具有两个int参数的方法。   问题是有两种方法同样好   根据Java的匹配方法调用的规则进行匹配   方法。消除现有的f()方法之一,错误将   走开。 - Ted Hopp

答案 2 :(得分:1)

f(1, 2);中,这两个数字都可以解释为intdouble,因此它不明确。你可以这样写:

f(1., 2);

f(1d, 2);

但是,使用具有相同参数数量的多个签名重载方法并不是一个好习惯。尽可能避免这种过载是一种很好的做法。

一个典型的例子,说明如何使用相同数量的参数重载问题,来自Joshua Bloch的Effective Java:

public class CollectionClassifier {
   public static String classify(Set<?> s) {
       return "Set";
   }
   public static String classify(Collection<?> c) {
       return "Unknown Collection";
   }
   public static void main(String[] args) {
       Collection<?>[] collections = {
           new HashSet<String>(),
           new ArrayList<BigInteger>()
       };
       for (Collection<?> c : collections) {
           System.out.println(classify(c));
       }
   }
}

这将打印Unknown Collection两次,很容易被忽视。