java中的方法重载解析

ayu*_*ush 14 java unboxing overloading

以下是我对java中重载解析的了解:


编译器尝试从给定的重载方法定义解析方法调用的过程称为重载解析.如果编译器找不到完全匹配,则仅通过使用upcast来查找最接近的匹配(从不进行向下转换).


这是一堂课:

public class MyTest {

    public static void main(String[] args) {
        MyTest test = new MyTest();
        Integer i = 9;
        test.TestOverLoad(i);
    }

    void TestOverLoad(int a){
        System.out.println(8);
    }

    void TestOverLoad(Object a){
        System.out.println(10);
    }

}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,输出为10.

但是,如果我稍微更改类定义并更改第二个重载方法.

public class MyTest {

    public static void main(String[] args) {
        MyTest test = new MyTest();
        Integer i = 9;
        test.TestOverLoad(i);
    }

    void TestOverLoad(int a){
        System.out.println(8);
    }

    void TestOverLoad(String a){
        System.out.println(10);
    }

}
Run Code Online (Sandbox Code Playgroud)

输出为8.

我在这里很困惑.如果永远不会使用向下转换,那为什么8会被打印出来呢?没有编译器为什么拿起TestOverLoad这需要方法int作为一个垂头丧气从论证Integerint

rge*_*man 20

编译器不会考虑向下转换,而是考虑重载解析的拆箱转换.在这里,Integer iint成功取消装箱.String不考虑该方法,因为Integer不能扩展到a String.唯一可能的重载是考虑拆箱的那个,所以8打印.

第一个代码输出的原因10是编译器将考虑通过拆箱转换扩展引用转换(Integerto Object).

在考虑适用哪种方法时,JLS第15.12.2节规定:

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

 

  1. 第二阶段(§15.12.2.3)执行重载解析,同时允许装箱和拆箱[...]


Ram*_*tra 13

在Java中,在方法重载的情况下解析方法是使用以下优先级完成的:

1.加宽
2.自动装箱
3.变速箱

java编译器认为扩展原始参数比执行自动装箱操作更令人满意.

换句话说,由于在Java 5中引入了自动装箱,编译器在选择较新的样式(自动装箱)之前选择较旧的样式(加宽),从而使现有代码更加健壮.与var-args相同.

在你的第一个代码段中,引用变量的扩大出现即IntegerObject,而不是未拳击即Integerint.在你的第二个片段中,扩展不可能发生Integer,String因此拆箱发生.

考虑以下程序,该程序证明了以上所有陈述:

class MethodOverloading {

    static void go(Long x) {
        System.out.print("Long ");
    }

    static void go(double x) {
        System.out.print("double ");
    }

    static void go(Double x) {
        System.out.print("Double ");
    }

    static void go(int x, int y) {
        System.out.print("int,int ");
    }

    static void go(byte... x) {
        System.out.print("byte... ");
    }

    static void go(Long x, Long y) {
        System.out.print("Long,Long ");
    }

    static void go(long... x) {
        System.out.print("long... ");
    }

    public static void main(String[] args) {
        byte b = 5;
        short s = 5;
        long l = 5;
        float f = 5.0f;
        // widening beats autoboxing
        go(b);
        go(s);
        go(l);
        go(f);
        // widening beats var-args
        go(b, b);
        // auto-boxing beats var-args
        go(l, l);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

double double double double int,int Long,Long

仅供参考,这是我的关于Java中方法重载的博客.

PS:我的答案是SCJP中给出的示例的修改版本.