从字节码看方法重载与重写

在Java中存在重载与重写,面试中经常会出现与之相关的问题,今天从字节码来看看他们的实现。

简单代码

简单的测试代码如下图:

1代码.png

其中有继承关系的三个类Animal、Mamml(哺乳动物)、Tiger,主要用来实现重写,AssignTest中有三个test方法用来实现重载,大家可以猜猜打印结果!

运行结果

运行结果如下图:
2运行结果.png
根据打印结果可以看到两个test方法执行的都是test(Animal)这个方法,两个name()方法却分别执行的Mammal与Tiger的两个类方法,代码比较简单,所以产生的结果也比较直接简单,接下来我们用字节码来分析分析!

方法字节码

main方法字节码指令如下图:
3字节码.png
字节码指令最重要的部分已经用红框圈出,其中第26行与31行为test方法,可以看到方法的参数都是Animal,说明在编译期就已经指定以具体的方法,从idea编辑器也可以看出来,只有test(Animal)方法被使用,这个在编译期就确定执行方法叫做方法的静态分派,重载就属于静态分派。

可是在35行与38行同样是执行Animal.name()方法,那么为什么会与上面不一样呢?这里就要说到invokevirtual这条指令了,invokevirtual指令会找到方法栈顶的第一个元素它所指向对象的实际类型,在这个实际类型中找对应的方法,如果存在就执行,否则​继续往上找,直到找到为止,这就叫方法的动态分配。

这这个例子中,虽然编译时表示的是执行Animal的name方法,可是从前面初始化的指令可以看到仍然是初始化具体的类型,所以他执行具体的方法。

综合代码

在AssignTest在加一个父类,实现重载与重写,同时把name()方法放到了test方法中,代码如下图:
4综合代码.png
运行的结果为Mammal、animal、Tiger、animal,说明执行的具体方法并没有发生变化,那么直接看字节码如下图:
5main字节码.png
可以看到字节码指定的方法还是AssignSuperTest.test(Animal)方法,不过我们从结果可以知道还是执行的AssignTest.test(Animal)方法,AssignTest.test(Animal)的字节码指令如下图:
6test字节码.png
AssignTest.test(Animal)在编译期并不知道传进来的Animal具体是什么类型,所以只能在运行期才能通过去查找具体的类型执行!

总结

从字节码来说,方法的重载实际上重载的几个方法已经是相互独立的方法,这与我们平时所理解是一致的(方法通过方法名与参数列表区分),而重写则不同,重写的目的是为了实现子类与父类不同的表现,是多态。

以最后一个例子为例,在test方法中执行name(),由于Animal具体的类型不知道,所以不知道会执行具体哪个name()方法。

所以方法重载是静态的,是编译器行为,是在写代码期或者编译器可以确定执行哪个方法,而方法重写是动态的,是运行期行为,只有在执行期才知道是具体哪个类型来执行方法。

只要理解了上面两句话在面试中遇到这类题就能够轻松解决。

Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!
Java程序员日常学习笔记

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值