重写、重载与静态分派、动态分派

前言

总所周知,封装、继承和多态是Java这门语言的三大特性,封装和继承是为了多态这一特性所做的铺垫,而重写和重载就是Java多态性的体现,其重要程度可想而知。静态分派、动态分派则是实现重写和重载的底层原理,因此学习静态分派和动态分派可以更好的理解Java多态这一特性。

重写和重载

重写(Override)体现在子父类之间,子类继承父类则继承父类的所有非私有方法,如果子类想要对父类方法进行修改,可以通过重写来优化或者实现子类自己的方法。

重写(Overload)是一个类中方法名相同,参数个数、参数类型不同的方法,它的目的是为了让方法的使用者可以不用记忆和理解那么多的方法名而设计的,它主要用于构造方法上。

静态类型和实际类型

public class Human{}
public class Man extends Human{}
public class Woman extends Human{}

Human human = new Man();

我们看上面这段代码,其中等号前半段的human为变量,“Human”为变量的静态类型,静态类型的变化仅仅在使用时发生,变量本身的静态类型是不会被改变的,静态类型在编译期就可知,而等号右边的“Man”则是变量的实际类型或者成为运行时类型,实际类型变化的结果需要在运行期才可确定。

简单来说就是,在编译期间,变量human的实际类型我们是不知道的,不知道它到底是Man还是Woman或者是个Human,只有在真正使用的时候我们才可以确定,但是在编译阶段我们是知道会有这个变化的,知道这个变化会在使用的时候发生,而且我们无论在哪个阶段都可以肯定的是human这个变量的静态类型就是“Human”。

静态分派和重载

所有依赖静态类型来决定方法执行版本的分派动作都成为静态分派,其最典型应用表现就是方法重载。

动态分派和重写

所有依赖实际类型来决定方法执行版本的分派动作都称为动态分派,其典型应用表现就是方法重写,动态分派发生在方法调用指令(指invokevirtual指令)执行时。

invokevirtual指令运行时解析过程大致分以下几步:

  1. 找到操作数栈顶的第一个元素所指向的对象的实际类型记作C

  1. 若在C中找到与常量中的描述符和简单名称都相符的方法,则进行访问权限校验,若通过则返回该方法的直接引用,查找结束,不通过返回异常

  1. 找不到方法则按继承顺序由下往上依次对C的父类进行搜索和验证

  1. 若始终找不到则抛异常

根据以上步骤可以看出,invokevirtual指令的第一步确定运行期接收者的实际类型是多态性的根源,同时我们也可以得出结论,这种多态性只会对方法有效,对字段无效,因为字段不使用这条指令,且字段在谁的方法中该字段的值就是该方法所属对象所赋予的值的大小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值