动态类型和静态类型
动态类型和静态类型发生在继承和多态中,在创建对象时,同一个对象有动态类型和静态类型之分,等号左侧的是静态类型,等号右侧new出来的类型是动态类型。
动态分派和静态分派
静态分派是在编译期发生,动态分派在运行期发生。
静态分派和动态分派涉及到对象的动态类型和静态类型。
方法执行时,方法传参进去,不管参数的动态类型是什么,都按照静态类型执行。
静态分派确定参数静态类型,动态分派决定执行者的类型。
class Father {
void eat(Father father) {
System.out.println("Father中的Father吃饭");
}
void eat(Son son) {
System.out.println("Father中的Son吃饭");
}
}
class Son extends Father {
void eat(Father father) {
System.out.println("Son中的Father吃饭");
}
void eat(Son son) {
System.out.println("Son中的Son吃饭");
}
}
public class 静态分派和动态分派 {
public static void main(String[] args) {
Father f1 = new Father();
Father f2 = new Father();
Father s1 = new Son();
Father s2 = new Son();
f1.eat(s1);
s1.eat(s2);
}
}
方法执行结果:
Father中的Father吃饭
Son中的Father吃饭
执行时,只考虑动态分派,第一条语句的方法调用者f1的动态类型是Father,参数s1的静态类型是Father,所以执行的结果是Father类中的eat(Father father)方法。
第二条语句的方法调用者s1的动态类型是Son,参数s2的静态类型是Father,所以执行的结果是Son类中的eat(Father father)方法。
这其实也是多态的特点:
- 对象类型和引用类型之间具有继承(类)/实现(接口)的关系;
- 引用类型变量发出的方法调用的到底是哪个类中的方法,必须在程序运行期间才能确定;
- 多态不能调用“只在子类存在但在父类不存在”的方法;
- 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。
注:虽然对于参数来说,也有动态类型和静态类型之分,但是不管是静态分派和动态分派,最终使用的都是参数的静态类型,所以我们不需要考虑参数的动态类型。