作者:雷哥来源|Java面试真题解析(ID:aimianshi666)转载请联系授权(微信ID:GG_Stone)面试合集:https://gitee.com/mydb/interview一个类中,定义了多个同名方法,但是每个方法的参数类型或参数个数不同,这就是方法重载。例如下面四种method方法都可以调用方法重载,如下代码所示:(Integerid,Stringname){//doSomething}}为什么不同的返回类型不算方法重载?要回答这个问题,首先要了解一下前置内容和方法签名。方法签名是一个唯一值,由方法名+参数类型+参数个数组成。这个唯一值就是方法签名,JVM(JavaVirtualMachine)通过这个方法签名来决定调用哪个方法。从方法签名的组成规则可以看出,方法的返回类型并不是方法签名的组成部分,所以当同一个方法中有多个方法名和参数相同但返回值类型不同的方法时类,JVM没有办法使用方法签名来决定调用哪个方法,如下图:为什么返回类型不能是方法签名的一部分?原因其实很简单。试想一下,如果方法的返回类型也是方法签名的一部分,那么当程序员编写代码调用“重载”的方法时,JVM无法分辨调用哪个方法,如下代码所示:publicclassOverloadExample{publicstaticvoidmain(String[]args){OverloadExampleexample=newOverloadExample();example.method("雷哥");//JVM应该调用哪个方法?}publicintmethod(Stringname){//doSomethingreturn666;}publicStringmethod(Stringname){//doSomethingreturn"雷哥聊编程";}}和上面的情况类似,JVM无法推断调用哪个方法,所以方法的返回类型不能用作方法签名的一部分。方法重载的使用场景方法重载的经典使用场景是String类型的valueOf方法。valueOf方法重载的实现有9种,如下图所示:它可以将数组、对象和基本数据类型转换成字符串类型。方法重载匹配原理方法重载的调用顺序不同,比如下面的代码:out.println("调用整数方法");}publicvoidmethod(longnum){System.out.println("调用长整数方法");}publicvoidmethod(Integernum){System.out.println("调用整数方法");}publicvoidmethod(Objectnum){System.out.println("调用对象方法");}publicvoidmethod(int...num){//可选参数System.out.println("调用int...方法");}}当方法重载时,程序应该调用哪个方法?上述程序的执行结果如下:因此,我们可以得出以下结论。匹配原则一:类型精确匹配方法重载会优先调用与方法参数类型相同的方法。这就是第一优先匹配原则:精确类型匹配。匹配原则2:基本类型自动转换成更大的基本类型接下来我们去掉精确匹配的方式,观察第二个匹配顺序是什么?实现代码如下:publicclassOverloadExample{publicstaticvoidmain(String[]args){OverloadExampleexample=newOverloadExample();example.method(12);}publicvoidmethod(longnum){System.out.println("calllongmethod");}publicvoidmethod(Integernum){System.out.println("调用整数方法");}publicvoidmethod(Objectnum){System.out.println("调用对象方法");}publicvoidmethod(int...num){//可选参数System.out.println("Callint...method");}}上面程序的执行结果如下图所示:因此,我们可以得出一个结论:如果是一个基础数据类型,那么方法重载调用的第二个匹配原则是自动转换为更大的基本数据类型。匹配原则三:自动装箱/拆箱匹配接下来,删除匹配原则二中的long方法,实现代码如下:publicclassOverloadExample{publicstaticvoidmain(String[]args){OverloadExampleexample=newOverloadExample();example.method(12);}publicvoidmethod(Integernum){System.out.println("调用整数方法");}publicvoidmethod(Objectnum){System.out.println("调用对象方法");}publicvoidmethod(int...num){//可选参数System.out.println("callint...method");}}上面程序的执行结果如下图所示:从上面的执行结果可以看出第三个方法重载的匹配原则是,匹配自动装箱或拆箱的数据类型。匹配原则4:按照继承路线向上匹配。这时候把第三个匹配原则中的Integer方法删掉,剩下的代码如下:){System.out.println("CallObjectmethod");}publicvoidmethod(int...num){//可选参数System.out.println("Callint...method");}}执行结果上述程序如下图所示:从上面的执行结果可以看出,方法重载的第四个匹配原则是依次匹配父类的方法调用。匹配原则5:可变参数匹配最后把代码中的方法删掉,只剩下一个可选参数。实现代码如下:publicclassOverloadExample{publicstaticvoidmain(String[]args){OverloadExampleexample=newOverloadExample();example.method(12);}publicvoidmethod(int...num){//可选参数System.out.println("callint...method");}}上面程序的执行结果如下图所示:从上面执行结果,我们可以看到,方法重载的第五个匹配原则是匹配可选参数。综上所述,同一个类中定义了多个同名方法,但每个方法的参数类型或参数个数不同,这就是方法重载。方法重载的典型使用场景是String中的valueOf方法,它有9种实现。方法返回类型不能用作方法重载的基础,因为它不是方法签名的组成部分。方法重载的匹配原则有5条:精确匹配、基本类型自动转换为更大的基本类型、自动装箱/拆箱匹配、根据继承路由向上匹配、可变参数匹配。
