我们知道Java面向对象包括抽象、封装、继承和多态四个特性,其中多态的实现主要有运行时多态(Override重写)和编译时多态(Overload重载),下面介绍一下这两者的区别。
Override(重写):是父类与子类之间多态性的一种方法,如果子类中的方法与父类有相同的名称、返回值和参数类型,则子类就是覆盖了父类的方法,JVM在调用的时候根据不同的对象实例调用不同的方法。
Overload(重载):发生在同一个类中,有相同的方法名称,但是参数类型或者参数个数或者参数顺序不同,就是方法重载,发生在编译阶段。
下图是方法重写和重载的区别:
具体来说:
Override:
- 子类中的方法和父类中的方法必须有相同的方法名、参数列表,返回值可以为父类返回值的子类型
- 若父类中的方法抛出异常,则子类中的方法只能抛出一样的或者子类异常,不能抛出新的或者更广的异常。
- final方法不能被重写,private方法不能被重写
同一个包中,子类可以重写父类protected或者public方法,不同包中只能重写public方法,并且子类的访问范围不能缩小,如父类是public,子类不能是protected
Overload:
1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序
2、不能通过访问权限、返回类型、抛出的异常进行重载;
3、方法的异常类型和数目不会对重载造成影响;
4、重载事件通常发生在同一个类中,不同方法之间的现象。
5、存在于同一类中,但是只有虚方法和抽象方法才能被覆写。
下面介绍调用对象的方法执行过程:- 虚拟机预先为每个类创建一个方法表,其中列出了所有方法的签名和实际调用的方法,在真正调用方法时,只需要查找这个表就可以。
- 编译器查看调用的方法名称和方法签名,比如调用x.f(“Hello”),这里x申明为类C的对象,则编译器去C类的方法表中查找f函数,如果存在多个名称为f的函数,就按照方法签名匹配,这就是重载解析。
- 如果调用的是private、static、final或者构造器方法,编译器可以很准确的知道应该调用哪个方法,这种方式是“静态绑定”。
- 当采用动态绑定时,先去类C的方法表中去匹配合适的方法,如果没有匹配到,再去类C的父类D的方法表中匹配,这就是重写方生的多态。