上篇回顾:多态是面向对象程序设计很是重要的特性,它让程序拥有 更好的可读性和可扩展性。ide
引用类型的变量具备两种类型:编译时类型和运行时类型。(也分别叫作声明类型和实际类型)举个简单的例子:设计
//假设Student类是Person类的子类 Person p = new Student();
Person
即为引用变量p的编译时类型。Student
即为引用变量p的运行时类型。将方法调用同方法主体关联起来被称为绑定。code
在程序执行前进行绑定,叫作静态绑定,也称做前期绑定。在面向过程的语言中是默认的绑定方式。对象
在Java中,用private、static和final修饰的方法(static和final以后会作出总结)或构造器可以准确地让编译器调用哪一个方法,就是静态绑定(static binding)。继承
在运行时根据对象的运行时类型进行绑定,叫作动态绑定,也叫作后期绑定。固然在Java中,除了静态绑定的那些方法,其余方法的调用方式就是动态绑定啦。编译器
public class DynamicBinding { //Object是全部类的超类,根据向上转型,该方法能够接受任何类型的对象 public static void test(Object x) { System.out.println(x.toString()); } public static void main(String[] args) { test(new PrimaryStudent());//Student test(new Student());//Student test(new Person());//Person test(new Object());//java.lang.Object@1b6d3586 } } class Person extends Object { @Override public String toString() { return "Person"; } public void run(){} public void count(int a){} } class Student extends Person { @Override public String toString() { return "Student"; } public void jump(){} } class PrimaryStudent extends Student { }
Object
。注意:引用变量只能调用编译时类型所具备的方法。咱们还能够发现,test(new PrimaryStudent());
的运行结果是Student
,,结果很明显,由于PrimaryStudent
类中并无重写父类的方法,若是采用动态绑定的方式调用方法,虚拟机会首先在本类中寻找适合的方法,若是没有,会一直向父类寻找,直到找到为止。虚拟机
那么,每次调用时都要向上寻找,时间开销必然会很大。为此虚拟机预先为每一个类都建立了方法表,其中列出了全部的方法签名(返回值类型不算)和实际调用的方法,这样子的话,在调用方法时直接查表就能够了。(值得一提的是,若是用super限定调用父类方法,那么将直接在实际类型的父类的表中查找)it
Person
类的方法表:Person: //下面省略Object方法签名 //xxx()-> Object.xxx() //方法签名->实际调用的方法 toString()->Person.toString() run()->Person.run() count(int)->Person(int)
Student
类的方法表:Student: //下面省略Object方法签名 //xxx()-> Object.xxx() //方法签名->实际调用的方法 toString()->Student.toString() jump()->Student.jump() run()->Person.run() count(int)->Person(int)
PrimaryStudent
类的方法表(PrimaryStudent
类为空,直接继承Student
类):PrimaryStudentt: //下面省略Object方法签名 //xxx()-> Object.xxx() //方法签名->实际调用的方法 toString()->Student.toString() jump()->Student.jump() run()->Person.run() count(int)->Person(int)
test(new PrimaryStudent());
语句时,虚拟机将会提取PrimaryStudent
的方法表。toString
签名的类。这时虚拟机已经知道须要调用Student
类型的toString()
方法。动态绑定大大提高了程序的可扩展性,好比,我如今要新增一个
Teacher
类,能够直接让Teache
r类继承于Person
类,再用Object
类的引用指向Teacher
对象,而不用作其余的代码调整,动态绑定自动搞定,就至关舒服。编译
参考书籍:《Thinking in Java》、《Java核心技术卷I》