Java多态调用机制理解
2017-08-30 15:19
169 查看
首先上难以理解的结论:
* 成员方法(非静态)(运行看
* 编译时, 如果父类没有, 则编译失败.
* 运行时, 多态调用的方法用的是
* 成员变量(运行编译看
* 编译时, 如果父类没有, 则编译失败.
* 运行时, 多态调用的成员变量用的是
再上演示代码:
父类
子类1: 男孩
子类2: 女孩
测试代码块
运行结果
![](https://app.yinxiang.com/shard/s6/res/b3e80a6e-7fff-41ce-891a-f7d4300522a8)
理解了上面的代码, 接下来看下上述代码相关的
![](https://app.yinxiang.com/shard/s6/res/fde40b85-b72f-45b9-b2b3-f3d1d128832f)
个人觉得这张图非常清晰.
要深入理解多态, 首先应该有下面相关概念:
1. 我认为Java能够实现多态的重要原因是有方法的动态绑定. 这也就是为什么成员变量没有多态调用一说, 方法却有. 实现动态绑定主要是基于下面说的方法表.
2.
3. 多态调用方法的大致过程: java编译器将java源代码编译成class文件,在编译过程中,会根据静态类型将调用的符号引用写到class文件中。在执行时,JVM根据class文件找到调用方法的符号引用,然后在静态类型的方法表中找到偏移量(我的理解就是索引号),然后根据this指针确定对象的实际类型1,使用实际类型的方法表,偏移量跟静态类型中方法表的偏移量一样,如果在实际类型的方法表中找到该方法,则直接调用,否则,按照继承关系从下往上搜索。
看到这里应该基本对多态调用的机制有了一个大概的认识了, 我这里主要为了做笔记, 如果想进一步深入了解, 请参考下面的博客:
http://www.2cto.com/kf/201603/496508.html
* 成员方法(非静态)(运行看
子类, 编译看
父类):
* 编译时, 如果父类没有, 则编译失败.
* 运行时, 多态调用的方法用的是
子类的方法, 如果子类没有则找父类的.
* 成员变量(运行编译看
父类):
* 编译时, 如果父类没有, 则编译失败.
* 运行时, 多态调用的成员变量用的是
父类的.
再上演示代码:
父类
public class Person { @Override public String toString(){ return "I'm a person."; } public void eat(){ System.out.println("Person eat"); } public void speak(){ System.out.println("Person speak"); } }
子类1: 男孩
public class Boy extends Person{ @Override public String toString(){ return "I'm a boy"; } @Override public void speak(){ System.out.println("Boy speak"); } public void fight(){ System.out.println("Boy fight"); } }
子类2: 女孩
public class Girl extends Person{ @Override public String toString(){ return "I'm a girl"; } @Override public void speak(){ System.out.println("Girl speak"); } public void sing(){ System.out.println("Girl sing"); } }
测试代码块
public static void main(String[] args) { Person boy = new Boy(); Person girl = new Girl(); System.out.println(boy); //==> I'm a boy boy.eat(); //==>Person eat boy.speak(); //==>Boy speak //boy.fight(); System.out.println(girl); //==>I'm a girl girl.eat(); //==>Person eat girl.speak(); //==>Girl speak //girl.sing(); }
运行结果
理解了上面的代码, 接下来看下上述代码相关的
内存模型
个人觉得这张图非常清晰.
要深入理解多态, 首先应该有下面相关概念:
1. 我认为Java能够实现多态的重要原因是有方法的动态绑定. 这也就是为什么成员变量没有多态调用一说, 方法却有. 实现动态绑定主要是基于下面说的方法表.
2.
方法表, 简单理解就是方法的列表, 每个类都有对应的方法表, 对于父子类同名方法在方法表中具有相同的索引号(专业点说, 就是具有相同签名的方法,在父类、子类的方法表中具有相同的索引号).
3. 多态调用方法的大致过程: java编译器将java源代码编译成class文件,在编译过程中,会根据静态类型将调用的符号引用写到class文件中。在执行时,JVM根据class文件找到调用方法的符号引用,然后在静态类型的方法表中找到偏移量(我的理解就是索引号),然后根据this指针确定对象的实际类型1,使用实际类型的方法表,偏移量跟静态类型中方法表的偏移量一样,如果在实际类型的方法表中找到该方法,则直接调用,否则,按照继承关系从下往上搜索。
看到这里应该基本对多态调用的机制有了一个大概的认识了, 我这里主要为了做笔记, 如果想进一步深入了解, 请参考下面的博客:
http://www.2cto.com/kf/201603/496508.html
this指针起了关键作用, 它相当于使得子类即使披着父类的妆容, 也不忘自身到底是谁. ↩
相关文章推荐
- JAVA多态机制中,成员调用的特点
- 深入java (类)对象初始化,类构造函数的调用以及多态(java中多态的实现机制以后补充)
- 理解java程序调用机制
- java多态机制理解以及强制类型转换(结合java与android)
- java方法的调用机制-一多态为例
- 初步理解Java的三大特性——封装、继承和多态
- 【转】深入理解 Java 垃圾回收机制
- 深入理解Java Proxy机制
- 深入理解JAVA多态原理
- 图说Java —— 理解Java机制最受欢迎的8幅图
- 理解 Java 垃圾回收机制
- 2013年图说Java —— 理解Java机制最受欢迎的8幅图
- (转)java提高篇(四)-----理解java的三大特性之多态
- 对Java和C#事件机制的理解
- (转)关于Java的反射机制,你需要理解这些..
- 关于java反射机制的粗略理解
- 深入理解Java的方法调用一(值传递和引用传递)
- C++和java中多态机制的异同
- Java事件机制理解及应用
- 深入理解java异常处理机制