override(重写、覆盖):
子类在继承父类时,重写(重新实现)父类中的方法。
重写(覆盖)的规则:
- 重写方法的参数列表必须完全与被重写的方法的相同,否则不能称其为重写而是重载.
- 重写方法的访问修饰符一定要大于被重写方法的访问修饰符(public>protected>default>private)。
- 重写的方法的返回值必须和被重写的方法的返回一致;
- 重写的方法所抛出的异常必须和被重写方法的所抛出的异常一致,或者是其子类;
- 被重写的方法不能为private,否则在其子类中只是新定义了一个方法,并没有对其进行重写。
- 静态方法不能被重写为非静态的方法(会编译出错)。
overload(重载、动态绑定):
重载的规则:
- 在使用重载时只能通过相同的方法名、不同的参数形式实现。不同的参数类型可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不一样);
- 不能通过访问权限、返回类型、抛出的异常进行重载;
- 方法的异常类型和数目不会对重载造成影响;
private、static、final方法或者构造器称为静态绑定
静态分派
所有依赖静态类型来定位方法执行版本的分派动作,都称为静态分派,静态分派的最典型应用就是多态性中的方法重载。静态分派发生在编译阶段,因此确定静态分配的动作实际上不是由虚拟机来执行的。参考如下例子:
class Human{
}
class Man extends Human{
}
class Woman extends Human{
}
public class StaticPai{
public void say(Human hum){
System.out.println("I am human");
}
public void say(Man hum){
System.out.println("I am man");
}
public void say(Woman hum){
System.out.println("I am woman");
}
public static void main(String[] args){
Human man = new Man();
Human woman = new Woman();
StaticPai sp = new StaticPai();
sp.say(man);
sp.say(woman);
}
}
结果如下
I am human
I am human
对于这一句中:
Human man = new Man();
“Human”称为变量的静态类型,后面的“Man”称为变量的实际类型。静态类型和实际类型在程序中都可以发生一些变化,区别是静态类型的变化仅仅在使用时发生,变量本身的静态类型不会被改变,并且最终的静态类型是在编译期可知的,而实际类型变化的结果在运行期才可确定。
动态分派
动态分派与多态性的另一个重要体现——方法覆写(向上转型后调用子类覆写的方法)有着很紧密的关系。在判断执行父类中的方法还是子类中覆盖的方法时,如果用静态类型来判断,那么无论怎么进行向上转型,都只会调用父类中的方法;然而实际中显然是使用变量的实际类型来分派方法的执行版本,而实际类型的确定需要在程序运行时才能确定下来,这种在运行期根据实际类型确定方法执行版本的分派过程称为动态分派
单分派与多分派
方法的调用者与方法的参数统称为方法的宗量。
- 单分派:根据一个宗量对目标方法进行选择
- 多分派:根据多于一个宗量对目标方法进行选择
Java 语言是一门静态多分派、动态单分派的语言——因为在调用重写方法时,调用者只有一个,重写方法参数类型选择也只有同样的参数类型(数量与变量类型),因而是动态单分派;而重载则可以有多个参数,因而是静态多分派
参考:http://wiki.jikexueyuan.com/project/java-vm/polymorphism.html
网友评论