java:引用..是不明确的,方法method1和method2在...匹配

时间:2014-03-06 19:50:24

标签: java overloading variadic-functions

我面对相同的代码:

    public class Devk{
        public static void tMeth(Integer... i){
          System.out.print("A");
        }
        public static void tMeth(int... i){
          System.out.print("B");
        }
        public static void main(String args[]){
          tMeth(Integer.valueOf("7"));//compile error
          tMeth(new int[2]); //returns B
          tMeth(new Integer[2]); //returns A
        }

  }

在调用后我看到了

java: reference to tMeth is ambiguous, both method tMeth(java.lang.Integer...) in GenericsTest.Test1 and method tMeth(int...) in GenericsTest.Test1 match

方法Integer.valueOf("7")返回Integer包装器。我希望在控制台中看到A

谁可以解释这种行为并为此提供一般规则?

P.S。

public static void tMeth(Integer i){
    System.out.print("A");
}
public static void tMeth(int i){
    System.out.print("B");
}
public static void main(String args[]){
    tMeth(1); //returns B
    tMeth(new Integer(1)); //returns A
}

4 个答案:

答案 0 :(得分:6)

编译方法调用时,编译器按此顺序搜索匹配方法:

  1. 尝试查找没有自动装箱/拆箱或varargs的方法。
  2. 如果找不到方法,请查看方法是否匹配使用自动装箱/拆箱。
  3. 如果仍然没有找到方法,请查看方法是否匹配使用varargs和autoboxing / unboxing。
  4. 在你的情况下,你在这里的步骤(3)。由于允许拆箱,因此两种方法均适用。

    然后编译器尝试找到最具体的那个。如果一种方法的参数类型具有相同或更具体的特征,则其中一种方法比另一种方法更具体(例如,StringObject更具体,intlong更具体})。

    但在intInteger之间,两者都不具体;编译器依赖于上面(2)之前的测试(1)来获得正确的方法,比如foo(int)foo(Integer)

    因此,有两种适用的方法,两者都没有更具体,因此存在模糊性错误。

    JLS reference

答案 1 :(得分:0)

此行为是由Java的自动装箱和Java的自动装箱引起的。

Java将自动将原始类型转换为其对应的包装类,并将包装类转换为其对应的基本类型。这使得可以将“int”传递给需要“整数”或“整数”的方法到需要“int”的方法。 Java将自动转换类型。

在您的特定情况下,这会导致歧义,因为有两种可能的方法可供调用。

您可以在此处详细了解 http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

答案 2 :(得分:-2)

Integer(以及DoubleByteFloatLong等)是原始数据类型的包装类。

自Java 5以来,由于自动装箱,您无法使用int和另一个使用Integer的方法,这会将任何int变量转换为其Integer对象(以及任何Integerint,如果对象为NullPointerException则提出null

答案 3 :(得分:-2)

这是因为一项名为“Autoboxing'在java中,给定的原始值将自动加入到它的包装类中。这里的原始值是int,包装类是Integer。由于7匹配原始值7和整数值7,因此两种方法都会发生冲突。

由于编译器会将原始值传递给匹配基元和包装器类型的参数(反之亦然,因为包装器类型),你实际上并没有像在复制它们那样重载方法。