使用java中的基本类型的变量参数重载时的奇怪行为

时间:2017-03-14 09:41:58

标签: java overloading variadic-functions autoboxing

显然,我对过载,自动装箱和变量参数的工作方式知之甚少。

因此,只要有原始类型的参与,这就是导致问题的程序。

public static void z(int a, Object...objects){
}
public static void z(Object...objects){
}
public static void main(String[] args) {
    z();    // no error
    z(4);   // Compile time Error : Ambiguous

    z2();               // No error
    z2(true, "sadas");  // Error

    // No problem with reference types
    z3();       // No error. String one called
    z3(5);      // No error. Object one called

    z4();       // Error
    z4(4);      // Error
    z4("asdas");    // Working properly
}
public static void z2(boolean b, Object...objects){
}
public static void z2(Object...objects){
}
public static void z3(String...objects){
    System.out.println("String one called");
}
public static void z3(Object...objects){
    System.out.println("Object one called");
}
public static void z4(int...objects){
    System.out.println("int z4 called");
}
public static void z4(Object...objects){
    System.out.println("Object z4 called");
}

任何人都可以解释为什么会发生这种情况吗?我可以高兴地使用整数,布尔而不是int,boolean但非常想知道它背后的内部工作

2 个答案:

答案 0 :(得分:2)

如果编译器无法确定应该使用哪个重载方法变体,则不会编译方法调用。

我们以z4为例:

  1. 方法调用z4()符合两种变体的签名。
  2. 方法调用z4(4)也适合两种变体的签名,因为变量可以自动装箱。
  3. 方法调用z4("asdas")不明确,因为String无法投放到int
  4. 更新:解决重载方法调用的规则如下:

      

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

         

    ...

         

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

         

    ...

         

    第三阶段(§15.12.2.4)允许重载与变量arity方法,装箱和拆箱相结合。

    如果在同一阶段选择了多个变体,则选择最具体的变体*,但简而言之z3(String...)z3(Object...)更具体,而z4(int...)和{ {1}}同样具体。

    *确定这个最具体的变体的规则有点复杂(见here

答案 1 :(得分:0)

这是一个晶圆厂问题

现在考虑

public static void z2(boolean b, Object... objects) {
    }

    public static void z2(Object... objects) {
    }

两种方法都有一个vararg参数,这意味着它们将在重载分辨率的第三个也是最后一个阶段被考虑。

记住Object类是java中所有对象的母亲

这解释了一件事

编译器可以将两者都视为将再次导致对象数组的对象。

现在终于

void z2(boolean b, Object... objects)
    public static void z2(Object... objects) 

被视为同一功能。

检查您是否可以发表评论

    z2(true); 
    z2(true, "sadas"); 

删除

中的任何一个
public static void z2(boolean b, Object... objects) {
            }
Or
    public static void z2(Object... objects) {
    }

这会奏效。 但是

您已在参数

中使用了对象

如果您具体例如

   public static void z2(boolean b, String... objects) {

        }
        public static void z2(String... objects) {
        }
z2(); // No error
z2(true, "sadas"); // No error

这种方式可以解决