1.What(是什么)
菜鸟教程上对于多态是什么,解释的非常通俗易懂
2.Why(为什么)
可以理解为,多态的优点是什么,这个菜鸟教程上也大致的描述了下
但是,如果想要继续深入的话,可以沿着这个方向一致追溯下去:
为什么要有多态?——>为什么面向对象三要素是继承、封装、多态?——>为什么要有面向对象?
你看,如果想要彻底知道为什么要有多态的话,就应该追溯到面向对象和面向过程的历史了,但是本文讲的主要是多态。所以这里不做太深讨论,
3.Where(在哪)
可以理解为应用在哪里,也可以反过来理解为,使用多态应该具备什么条件?还是在菜鸟教程上
4.How(怎么做)
也就是怎么实现,如下图
在Java中,重写和重载可以算是多态最简单易懂的体现了。
而重载的具体实现是在javac命令的编译阶段,会根据参数的静态类型去选择对应的方法。
重写则是在运行阶段根据实际类型选择对应的方法。那么具体是怎么做的呢?
其实也就是invokevirtual指令的运行过程中的一部分:在查找方法的时候,先把对应的方法名、返回值、参数类型在子类中的方法表中查找一遍,如果没有,则去父类中的方法表再找一遍,直到找到Object类中,没有则抛出异常。
不过上面的流程其实也是虚拟机在分派是会做什么,具体怎么做实际上是在方法区中为类建立一个虚方法表,去代替查找方法以提高性能。
如上图所示(摘自《深入理解Java虚拟机》),在Son方法表中会有对应的引用指向Object类的toString()方法,当在调用Son类的toString()方法时,会直接调用Object的toString()方法,不用再去对Son类的各个父类依次查找了。
本质区别就在于,一个是直接调用,一个是先查找再调用,可想而知,当然是先者效率高上许多。
当然你可能会想,直接调用的话,如果调用一个不存在的方法,不是就直接报错了吗?首先,调用一个不存在的方法,在编译的时候就不会通过,其次,通过别的手段调用了不存在的方法并且正常编译了,最多就报个错抛出异常,但是效率却能快上很多,怎么取舍显而易见了。
(隔了很久没写博客,也是自己偷懒了,本来这篇也不太想写的,因为写到一半,发现书上讲的很清楚,自己再写如果没有一些自己的东西感觉写出来很多余,但是写都写了,而且,自我感觉那个思维导图总结还可以,所以就。。。写完算了,写的有什么不对的欢迎留言交流)