编译器的模糊参数,当它对我来说不明确时

时间:2013-08-03 09:33:30

标签: java compiler-construction

为什么编译器在这里抱怨?

public static void main(String[] args) {
    flipFlop(new Integer(11), 20f);
}

private static void flipFlop(int i, Float iRef) {

}

private static void flipFlop(int i, float j) {

}

但不是吗?

public static void main(String[] args) {
    flipFlop(11, 20f);
}

private static void flipFlop(int i, Float iRef) {

}

private static void flipFlop(int i, float j) {

}

这很奇怪,因为它应该在两种情况下解决。

在某些情况下,只有第二个参数可能会变得模棱两可,而第一个参数则不然。那么,如果我改变第一个,为什么还要抱怨呢。

4 个答案:

答案 0 :(得分:4)

当多种方法适用时,编译器会尝试查找最具体的方法。如果两个方法最具体,那么就会出现歧义,并且会出现错误。

总之(actual rules稍微复杂一点):

  • 编译器首先查找适用的方法而不允许varargs或(un-)装箱。在第二个示例中,仅应用第二种方法并进行选择。在您的第一个示例中,需要取消整理Integer,并且在此阶段无法选择任何方法。
  • 编译器然后允许装箱和拆箱。在您的第一个示例中,两种方法都适用。
  • 然后编译器确定which method is more specific:在你的情况下,没有一个在规范中定义的意义上更具体,因为float和Float之间没有关系(例如:如果你有一个float和一个double,float会更具体;如果你有一个浮点数和一个数字,浮点数会更具体。)

答案 1 :(得分:1)

在第二种情况下,您与方法签名完全匹配。在第一种情况下,它是模棱两可的。您是否取消IntegerFloat

的框

答案 2 :(得分:0)

在第一种情况下,您将值设置为和Integer,并且在收到时不会取消装箱,因为它应该是和int,JVM在参数的情况下不会取消装箱。 在第二种情况下,你给int参数赋一个原始类型int,第二个参数是autoboxed。

答案 3 :(得分:0)

您的第二个示例与第二个flipFlop的签名匹配。第一个调用不匹配flipFlops,因此编译器尝试选择最具体的匹配,并且两者都具有相同的特定性,因为两者都需要装箱/取消装箱才能匹配。由于它们同样适用,因此呼叫含糊不清。

请参阅Java语言规范,条款15.12方法调用表达式。