Java 方法重载-对的引用不明确

Java 方法重载-对的引用不明确,java,overloading,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 s

我试图更好地掌握函数重载

我有这个测试程序请原谅我的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);
存在编译器错误,*对f的引用不明确*

为什么会出现这种错误?我们不是在叫fint,int吗?但是没有声明这样的方法。我原以为没有为f找到合适的方法,但我没有找到,为什么?

int在所有这些语言中都可以转换为double,因此如果只有其中一种可用,那么很容易:将需要转换为double的值转换为double,然后调用该方法

但是在这种情况下,这两种方法都是有效的,因为每种方法都可以单独使用,但两者都不比另一种好,因为在每种情况下,一个参数只需要标识int-to-int转换,另一个参数需要int-to-double转换。因此,在Java和C中,它都是模棱两可的,并且会因编译时错误而失败。我想这也是它在C++中所做的,但我不确定。在Java和C中,如果您还有一个方法static void fint x,int y,那么对于该方法调用来说,它无疑比其他两个方法中的任何一个都要好

如有疑问,应参考相关的语言规范。对于Java,是相关的部分。在中,是第7.5节。

int在所有这些语言中都可以转换为double,因此如果只有其中一种语言可用,那么很容易:将需要转换为double的值转换为double,然后调用该方法

但是在这种情况下,这两种方法都是有效的,因为每种方法都可以单独使用,但两者都不比另一种好,因为在每种情况下,一个参数只需要标识int-to-int转换,另一个参数需要int-to-double转换。因此,在Java和C中,它都是模棱两可的,并且会因编译时错误而失败。我想这也是它在C++中所做的,但我不确定。在Java和C中,如果您还有一个方法static void fint x,int y,那么对于该方法调用来说,它无疑比其他两个方法中的任何一个都要好


如有疑问,应参考相关的语言规范。对于Java,是相关的部分。在中,是第7.5节。

这些函数彼此非常接近,或者对编译器来说意义更模糊,因此编译器看到这些函数会感到困惑

static void f(int x, double y)

static void f(double x, int y)
为了消除编译器的这种混乱或歧义,简单地添加以下内容

 static void f(int x, int y)
我认为这句话对你解释得更好


问题不是缺少一个具有两个int参数的方法。 问题是有两种方法同样好 根据Java的匹配方法调用的规则进行匹配 方法。消除一个现有的f方法,错误将消失 走开特德霍普


这些函数彼此非常接近,或者对编译器来说意义更模糊,因此编译器会对它们感到困惑

static void f(int x, double y)

static void f(double x, int y)
为了消除编译器的这种混乱或歧义,简单地添加以下内容

 static void f(int x, int y)
我认为这句话对你解释得更好


问题不是缺少一个具有两个int参数的方法。 问题是有两种方法同样好 根据Java的匹配方法调用的规则进行匹配 方法。消除一个现有的f方法,错误将消失 走开特德霍普

f1中,2;这两个数字都可以解释为int或double,因此它是不明确的。你可以这样写来澄清:

f(1., 2);

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

Joshua Bloch的《高效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));
       }
   }
}
这将打印两次未知集合,很容易忽略;这两个数字都可以解释为int或double,因此它是不明确的。你可以这样写来澄清:

f(1., 2);

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

Joshua Bloch的《高效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));
       }
   }
}

这两个集合将打印两次,并且它很容易被忽略。

我也很想知道C++和C的结果是什么,你可以尝试一下。问题不是没有合适的方法,这是因为有两个,而且没有一个是更好的匹配,根据java的规则,实际调用参数比其他。我还想知道C++和C的结果是什么,你可以尝试自己。问题不是没有。
合适的方法是,有两个,根据Java的规则,两者都不能比另一个更好地匹配实际的调用参数。我们没有fint,int。这不意味着我们根本没有这个方法,所以我希望有一个“methodnotfound”。当你的代码中没有它时,你根本就没有它。你必须定义它,这样你才能拥有它。问题不是缺少一个有两个int参数的方法。问题是,根据Java将方法调用匹配到方法的规则,有两个方法是同样好的匹配。删除一个现有的f方法,错误就会消失。@Tedhopp当我看到代码时,你是完全正确的,我突然意识到:谢谢你更新了答案Kick,它现在有了一些意义。这是我没有得到的。我们没有fint,int。这不意味着我们根本没有这个方法,所以我希望有一个“methodnotfound”。当你的代码中没有它时,你根本就没有它。你必须定义它,这样你才能拥有它。问题不是缺少一个有两个int参数的方法。问题是,根据Java将方法调用匹配到方法的规则,有两个方法是同样好的匹配。删除一个现有的f方法,错误就会消失。@Tedhopp当我看到代码时,你是完全正确的,我突然意识到:感谢更新的答案提示,它现在有了一些意义。谢谢,从规范检查是个好主意,从来没有想过。谢谢,从规范检查是个好主意,从来没有想过。