在Java中传递方法的参数变得模棱两可时?

时间:2017-02-04 20:26:31

标签: java parameter-passing overloading

当方法重载完成后,我知道只有方法签名不同才能创建具有相同名称的方法。

class Demo{
    public static void myMethod(int y, double x){}
    public static void myMethod(double x,int y){}

    public static void main(String args[]){
        byte b=10;
        myMethod(b,b);
    }
}

上面显示的代码显示错误错误:对myMethod的引用不明确 出现此问题的原因是自动转换后可以将字节值分配给int和double类型,并且令人困惑的是要将值传递给哪个方法? 如果我错了,请纠正我。

我尝试了以下程序。我认为这也会产生错误,但编译没有错误

class MyClass{
    public static void myMethod(int i){
        System.out.println("myMethod1(int)");
    }
    public static void myMethod(double a){
        System.out.println("myMethod2(int)");
    }   
}

class Demo{
    public static void main(String args[]){
        MyClass.myMethod(100);
    }
}

我认为它也会提供与之前相同的错误,但这会将输出作为 myMethod(int) ...所以我假设因为它有一个完全匹配的方法可以传递int值,它不会给出错误..

但如果我对上面的第二个程序进行以下更改,为什么不给出错误?

class MyClass{
    public static void myMethod(int i){
        System.out.println("myMethod1(int)");
    }
    public static void myMethod(double a){
        System.out.println("myMethod2(int)");
    }   
}

class Demo{
    public static void main(String args[]){
        byte b=10;
        MyClass.myMethod(b);
    }
}

该字节可以自动转换为int和double对吗?输出为 myMethod(int) .. 这不应该让编译器感到困惑并且给错误提供对myMethod的引用是不明确的 ??

3 个答案:

答案 0 :(得分:1)

class MyClass{
    public static void myMethod(int i){
        System.out.println("myMethod1(int)");
    }
    public static void myMethod(double a){
        System.out.println("myMethod2(int)");
    }   
}

class Demo{
    public static void main(String args[]){
        MyClass.myMethod(100);
    }
}

输出是myMethod1(int),因为java integer literal的默认类型是整数。所以它需要最接近的匹配并调用myMethod(int i)

class MyClass{
    public static void myMethod(int i){
        System.out.println("myMethod1(int)");
    }
    public static void myMethod(double a){
        System.out.println("myMethod2(int)");
    }   
}

class Demo{
    public static void main(String args[]){
        byte b=10;
        MyClass.myMethod(b);
    }
}

这不会给编译器带来歧义,因为您发送的参数是字节,字节被加宽以匹配方法参数。如果您声明myMethod(short i),它会调用此而不是myMethod(int i)。这就是java中扩展的工作方式。

byte->short->int->long

class Demo{
    public static void myMethod(int y, double x){}
    public static void myMethod(double x,int y){}

    public static void main(String args[]){
        byte b=10;
        myMethod(b,b);
    }
}

编译器在上面的代码片段中发现了一个歧义,因为byte b被扩展为int,现在这两个方法的参数声明都为(double,int) (int,double),因此存在歧义,因为声明都有int变量因此会为编译器本身造成混淆。尝试在声明中将方法声明之一更改为(double,double) and you'll see that it calls the one that has int`。我所说的例子是

class Demo{
    public static void myMethod(double y, double x){}
    public static void myMethod(double x,int y){}

    public static void main(String args[]){
        byte b=10;
        myMethod(b,b);
    }
}

在这种情况下,它会调用myMethod(double x, int y)

如需更多许可,请参阅JLS

答案 1 :(得分:0)

它知道推广到.... <tr> <td>123</td> <td>456</td> </tr> .... 而不是促销到int,但是您已经在两种方法之间做出选择,这两种方法都需要升级到double,所以它不会不知道你的意思。

答案 2 :(得分:-1)

为了理解这类问题,你应该记下三分之一:

编译器总是尝试选择最具体的方法,并对参数进行最少的修改。

Java设计人员已经决定旧的代码应该在装箱取消装箱功能可用之前完全像以前一样工作。

加宽优于装箱/拆箱(因为上述原因),而后者则优于var-args。