为什么带签名(primitive,wrapper)和(primitive,primitive)的两个方法会导致方法调用(包装器,原语)不明确?

这只是一个练习,但我无法弄清楚这种模糊性:

private static void flipFlop(String str, int i, Integer iRef) { System.out.println(str + "ciao"); } private static void flipFlop(String str, int i, int j) { System.out.println(str + "hello"); } public static void main(String[] args) { flipFlop("hello", new Integer(4), 2004); } 

它说:

对于类型Test,方法flipFlop(String,int,Integer)是不明确的

我猜想第二个参数将被解包为int ,因此第二个flipFlop方法将是选择。

如果您喜欢精湛的阅读, 这里是Java语言规范的相关部分 ,描述了如何解决方法。

但基本上你的第三个参数可以被解释为原始或自动装箱的包装器,编译器无法弄清楚你想要什么。 这两种方法都是“ 最具体 ”的,可以使用JLS术语。

好吧,我已经仔细研究了JLS,我相信这应该可以解决你可能遇到的任何疑虑。

这是原始问题:

 public class Main { private static void flipFlop(int i, Integer iRef) { System.out.println("Method 1"); } private static void flipFlop(int i, int j) { System.out.println("Method 2"); } public static void main(String[] args) { flipFlop(new Integer(4), 2004); } } 

正如在另一个答案中指出的那样:这会失败,因为编译器无法决定使用什么重载。

但是你可能认为这没有任何意义。 在这种情况下编译器可以判断他应该使用什么方法:

 public class Main { private static void flipFlop(Integer y) { System.out.println("ciao"); } private static void flipFlop(int j) { System.out.println("hello"); } public static void main(String[] args) { flipFlop(new Integer(6)); flipFlop(6); } } 

理性告诉我们,当你有值X + Y和两个分别取Y + XY + Y并且你知道XY是可互换的,那么这意味着后一种方法更具体。

这两者之间的区别在JLS中描述。 我在下面提供了整个工作流程,但重要的是:

首先,编译器将查看具有相同签名的方法,同时禁止装箱/取消装箱。 在我们的第二个例子中,这不会引起任何问题,但在我们的第一个例子中,这并没有返回一个令人满意的方法,因为它们都没有将Integer作为第一个参数。

当失败时,编译器继续进行允许装箱/拆箱的第二步。 这应该解决我们对第一个参数的问题,但现在引起第二个参数的歧义,因为现在不确定你是使用int引用重载还是使用Integer引用重载。

这最终会导致模糊的方法调用。

15.12.2。 编译时间步骤2:确定方法签名

  1. 第一阶段( §15.12.2.2 )执行重载解析而不允许装箱或拆箱转换 ,或使用变量arity方法调用。 如果在此阶段没有找到适用的方法,则处理继续到第二阶段。

  2. 第二阶段(第15.12.2.3节 )执行重载解析, 同时允许装箱和拆箱 ,但仍然排除使用变量arity方法调用。 如果在此阶段没有找到适用的方法,则处理继续到第三阶段。

如果在适用性测试的三个阶段之一中确定了几种适用的方法,则选择最具体的方法,如第15.12.2.5节所述 。

15.12.2.5。 选择最具体的方法

如果方法可访问且适用,并且没有其他适用且可访问的方法严格更具体,则称该方法对于方法调用是最大特定的。

可能没有方法是最具体的,因为有两种或更多种方法是最具体的。 在这种情况下:

  • 如果所有最大特定方法都具有覆盖等效( §8.4.2 )签名,则:( ……一些规则来决定谁被选中……)

  • 否则,我们说方法调用是不明确的,并且发生编译时错误。

由于自动装箱 ,你的第二个参数2004也是一个int也适用于Integer ,这就是编译器无法决定使用哪种方法的原因。