重载(Overload)和重写(Override)解析

个人博客:www.letus179.com

概念

重载Overload

重载发生在一个类中,同名的方法如果有不同的参数列表参数类型不同参数个数不同或者二者都不同)。

  • 访问修饰符:重载与访问修饰符无关
  • 返回类型: 重载与返回值无关
  • 方法名: 重载方法名需完全一致
  • 参数列表: 重载参数列表需完全不同
重写Override

发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问不能比父类被重写方法声明更多的异常(里氏代换原则)。

  • 访问修饰符:子类的访问修饰符权限 >= 父类的访问修饰符权限
  • 返回类型: 子类的返回类型 <= 父类的返回类型
  • 方法名: 方法名应完全一致
  • 参数列表: 参数列表应完全一致

举例String类

重载例子

String类的构造器重载

    public String() {
        this.value = new char[0];
    }

    public String(char value[]) {
        this.value = Arrays.copyOf(value, value.length);
    }

String类的valueOf()方法的重载:

  public static String valueOf(char data[]) {
        return new String(data);
    }

    public static String valueOf(char data[], int offset, int count) {
        return new String(data, offset, count);
    }

重写例子

ArrayList继承了AbstractList

public class ArrayList<E> extends AbstractList<E>

AbstractList类中有方法add()

public boolean add(E e) {
        add(size(), e);
        return true;
    }

ArrayList类中有重写了add()方法:

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

多态

面向对象编程有三大特性:封装继承多态

概念

指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

实现多态的技术称为:动态绑定(dynamic binding)
多态存在的三个必要条件

1. 要有继承;
2. 要有重写;
3. 父类引用指向子类对象。

根据何时确定执行多态方法中的哪一个,多态分为两种情况:编译时多态运行时多态。顾名思义,如果在编译时能够确定执行多态方法中的哪一个,称为编译时多态,否则称为运行时多态。

编译时多态

重载都是编译时多态,从上面的分析可以看到,只要确定了方法参数的数据类型,个数,次序就能确定调用哪一个方法。

运行时多态

重写有两种多态性,当对象引用本类实例,此时为编译时多态,能在编译期确定调用哪个方法;否则为运行时多态

举例分析

package test;

public class Test {

}
class Animal{
    public String getName() {
        return "Animal";
    }
}
class Dog extends Animal {
    public String getName() {
        return "Dog";
    }
}

1.执行下面的main方法

    public static void main(String[] args) {
        Animal animal = new Animal();
        Dog dog = new Dog();
        System.out.println(animal.getName());
        System.out.println(dog.getName());
    }

输出结果:

Animal
Dog

AnimalDog引用的都是本类的实例

Animal animal = new Animal();
Dog dog = new Dog();

2.若是这样呢?输入结果是多少

    public static void main(String[] args) {
        Animal animal = new Dog();
        System.out.println(animal.getName());
    }

此时输出:

Dog

程序在运行时,会从实例所属的类开始寻找匹配的方法来执行,若是找不到匹配的方法,会按照继承关系逐层向上查找,直到超级父类Object类
该例子animal.getName()执行过程是:
查找匹配执行方法流程

3.修改Animal类, 空类

class Animal{
}

此时执行方法:

    public static void main(String[] args) {
        Animal animal = new Dog();
        System.out.println(((Dog) animal).getName());
    }

需要显示地转换下((Dog) animal).getName(),因为Animal类中没有定义getName()方法。

4.修改Animal,Dog类的getName()方法为静态方法,并增加一成员变量name

class Animal {
  public String name = "a";

  public static String getName() {
    return "Animal";
  }
}

class Dog extends Animal {
  public String name = "d";

  public static String getName() {
    return "Dog";
  }

执行main方法:

  public static void main(String[] args) {
    Animal animal = new Dog();
    System.out.println(animal.getName());
    System.out.println(animal.name);
  }

输出结果为:

Animal
a

结果解释:
1.重写只使用于实例方法,不能用于静态方法,对于static方法,只能隐藏,重载,继承
2.在利用引用animal访问对象的属性name或静态方法getName()时,是引用类型决定了实际上访问的是哪个对象(Animal)的成员,而不是当前引用代表的那个类(new Dog());
由此可知,子类静态方法并不能重写覆盖)父类的静态方法;故而输出的结果都是父类的成员结果。

为什么不能根据返回类型来区分重载

假设下面的重载方法update能编译通过

public class Test {

  public void update() {
  }

  public int update() {
    return 0;
  }
}

当调用new Test().update()时,不需要返回值, 这样就不能区分具体是调用哪个方法了。
方法的返回值,只能作为方法运行之后得一个状态,它是保持方法的调用者与被调用者进行通信的关键,并不能作为某个方法的标示.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值