我敢打赌很多人还不清楚JAVA方法重载

在这里插入图片描述

JAVA方法重载

  • 方法返回值不能作为重载的依据
  • 静态类型判断使用哪个方法重载
  • 通过自动装箱和扩大基础类型的值来选择方法重载

下面我们来一一介绍这些内容

方法返回值不能作为重载的依据

方法名相同但是方法的形式参数不同的一些方法,称这些方法为重载的方法。形式参数不同可以分为参数的类型不同,和参数的顺序不同。方法名和方法的形式参数我们称为方法的签名。区分方法的重载靠的是方法的签名,而与方法的返回值没有关系。下面我来解释下为什么方法的返回值不能作为方法重载区分的条件。有如下两个方法:

void f(){}
int f(){}

只要编译器可以根据语境明确判断出语义,比如在int x = f()中,那么的确可以据此区分出重载的方法。不过,有的时候你不关心返回值,比如下面这样:

f() ;

此时,java就不知道该调用哪个方法了。所以根据方法的返回值来区分方法重载是行不通的。

静态类型判断使用哪个方法重载

下面带给大家看一道经常用作java面试题来解释方法重载的过程。

public class StaticDispatch {
    static abstract class Human{}
    static class Man extends Human{}
    static class Woman extends Human{}
    public void sayHello(Human guy){ //1
        System.out.println("hello guy");
    }
    public void sayHello(Man guy){ //2
        System.out.println("Hello ,Man");
    }
    public void sayHello(Woman guy){ //3
        System.out.println("Hello ,Woman");
    }
    public static void main(String[] args) {
        Human man = new Man() ;
        Human woman = new Woman() ;
        StaticDispatch sr = new StaticDispatch() ;
        sr.sayHello(man);
        sr.sayHello(woman);
    }
}
//hello guy
//hello guy

我们看到分别传入man和woman这两个对象,输出的结果都是hello guy。说明都调用了代码中 sayHello(Human guy)方法。那么为什么会调用这个方法呢?下面我们先解释下这两个概念。

 Human man = new Man() ;

这个代码的Human称为静态类型,而后面的Man称为实际类型。而方法调用时,是看传入方法的参数的静态类型,也就是Human作为依据来查找匹配的方法,因为这两个对象的静态类型都是Human,所有都是调用 sayHello(Human guy)方法。

通过自动装箱和扩大基础类型的值来选择方法重载

上面讲到了通过方法传入参数的静态类型来选择方法重载,下面讲解通过自动装箱和其他机制来选择方法重载。我们也是通过一个代码来解释。

public class Overload {
   public static void sayHello(char arg){ //1
        System.out.println("hello char");
    }
    public static void sayHello(int arg){//2
        System.out.println("hello int");
    }
    public static void sayHello(long arg){//3
        System.out.println("hello long");
    }
    public static void sayHello(float arg){//4
        System.out.println("hello float");
    }
    public static void sayHello(double arg){//5
        System.out.println("hello double");
    }
    public static void sayHello(Character arg){//6
        System.out.println("hello Character");
    }
    public static void sayHello(Serializable arg){//7
        System.out.println("hello Serializable");
    }
    public static void sayHello(Object arg){//8
        System.out.println("hello object");
    }
    public static void sayHello(char... arg){//9
        System.out.println("hello char...");
    }

    public static void main(String[] args) {
        sayHello('a');
    }
}
//hello char

上述代码毫无疑问会输出hello char。如果注释掉sayHello(char arg)方法后会调用sayHello(int arg)方法。这是当找不到方法参数为char类型的sayHello方法后,‘a’会代表97(字符‘a’的Unicode数值为十进制数字97),因此会调sayHello(int arg)方法。同样,在找不到int类型为参数的方法时,会调用long类型为参数的方法。查找顺序是char》int》long》float》double。当把这5个方法都注释掉,会调用参数类型为Character的sayHello方法。这时发生了一次自动装箱,'a’被包装为它的封装类型java.lang.Character。

当我们把Character类型为参数的方法也注释掉,会发现输出结果为hello Serializable。这时就会让人感觉疑惑了。其实当找不到Character类型为参数的方法后,会去寻找这个类型的父类,而Serializable正是Character的父类,因此把Serializable为参数类型的方法注释掉后,会输出hello object。因为Object是所有未显示继承其他类的父类。当我们把sayHello(Object arg)方法也注释掉,会调用sayHello(char… arg)方法。因此,可见变长参数的重载优先级是最低的。

总结下上面寻找方法重载的步骤

  • 先按照参数类型为 char》int》long》float》double 顺序来寻找为方法
  • 当上面的寻找不到时,会发生自动装箱,去选择自动装箱后的类,然后按照父类一层层去寻找
  • 最后时可见变长参数的重载

好了,这就是方法重载的一些需要特别注意的地方。多说一句,以后再面试中再问到关于方法重载的时候,如果能回答到上面提到的这几点,那么面试官会对你刮目相看的,因为大多数人只知道方法重载的定义,而对其中的一些特性不了解。最后,我想说的是,基础的重要性,尤其是应届生去面试的时候,更是这样。有很多人走错了弯路,把学习的重点花在学习各种框架,其实以我的面试经历来说,真的大多数面试官喜欢考察基础,尤其是你对一些基础理解的比其他人深入的情况下,那么你得到offer的概率就会变大。

最后欢迎大家关注我的微信公众号“javams” 我为大家准备了一份非常详细的面试题,只要回复“面试”关键字就可以领取,同时希望大家与我相互讨论学习心得和技术。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值