java中的多态体如今重写和重载上,重载就属于静态分派,而重写属于动态分派。那咱们先来弄清楚什么是静态类型,什么是动态类型。例如:java
public class Son extends Father{} Father a = new Son();
对于以上代码:Father属于静态类型,Son属于动态类型。ide
所谓静态类型是指在程序编译期间就彻底肯定,而动态类型则是在程序运行期间才能够肯定。spa
下面,咱们来看看一个静态分派的例子:code
package fenixsoft; public class StaticDispatch { //父类 static abstract class Human{ } //子类1 static class Man extends Human{ } //子类2 static class Woman extends Human{ } /* * 三个重载的方法 */ public void say(Human guy){ System.out.println("hello,guy"); } public void say(Man guy){ System.out.println("hello,guy"); } public void say(Woman guy){ System.out.println("hello,guy"); } public static void main(String[] args){ StaticDispatch sd = new StaticDispatch(); Human man = new Man(); Human woman = new Woman(); sd.say(man); sd.say(woman); } }
这是这个例子的输出结果:对象
hello,guy hello,guy
下面咱们来分析为何会输出这样的结果:编译器
因为动态类型在编译期间不可知,因此编译器在编译程序时并不知道纯金的参数的实际类型是什么,也就是说,在上面的例子中,编译器不知道man和woman的实际类型,因此编译器在重载时只能经过他们的静态类型来肯定他们的类型。因此,java中重载时是经过参数的静态类型,而不是实际类型(动态类型)做为判断依据的。对于此例来讲,他们的静态类型就是Human,因此输出了这个结果。编译
那咱们再来看一个动态分派的例子:class
package fenixsoft; public class DynamicDispatch { static abstract class Human{ protected abstract void say(); } static class Man extends Human{ @Override protected void say() { // TODO Auto-generated method stub System.out.println("man,hello"); } } static class Woman extends Human{ @Override protected void say() { // TODO Auto-generated method stub System.out.println("woman,hello"); } } public static void main(String[] args){ Human man = new Man(); Human woman = new Woman(); man.say(); woman.say(); } }
此例的输出以下:引用
man,hello woman,hello
和静态分派相反,动态分派是经过对象的实际类型做为判断依据的。因此java中的重写是动态分派。就是在运行期间肯定接受者的实例类型,将类方法中的符号引用解析到了不一样的直接引用上,这就是方法重写的本质。程序