您的位置:首页 > 编程语言 > Java开发

Java多态调用机制理解

2017-08-30 15:19 169 查看
首先上难以理解的结论:

* 成员方法(非静态)(运行看
子类
, 编译看
父类
):

* 编译时, 如果父类没有, 则编译失败.

* 运行时, 多态调用的方法用的是
子类
的方法, 如果子类没有则找父类的.

* 成员变量(运行编译看
父类
):

* 编译时, 如果父类没有, 则编译失败.

* 运行时, 多态调用的成员变量用的是
父类
的.

再上演示代码:

父类

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 多态