Java多态之动态绑定
Java多态之动态绑定
上篇回顾:多态是面向对象程序设计非常重要的特性,它让程序拥有 更好的可读性和可扩展性。
- 发生在继承关系中。
- 需要子类重写父类的方法。
- 父类类型的引用指向子类类型的对象。
自始至终,多态都是对于方法而言,对于类中的成员变量,没有多态的说法。
上篇说到:一个基类的引用变量接收不同子类的对象将会调用子类对应的方法,这其实就是动态绑定的过程。在理解动态绑定之前,先补充一些概念。
引用变量的类型
引用类型的变量具有两种类型:编译时类型和运行时类型。(也分别叫做声明类型和实际类型)举个简单的例子:
//假设Student类是Person类的子类
Person p = new Student();
编译时类型
- 也叫声明类型,即由声明变量时的类型所决定。
- 上式的
Person
即为引用变量p的编译时类型。
运行时类型
- 也叫实际类型,即由指向对象的实际类型所决定。
- 上式的
Student
即为引用变量p的运行时类型。
方法绑定
将方法调用同方法主体关联起来被称为绑定。
静态绑定
在程序执行前进行绑定,叫做静态绑定,也称作前期绑定。在面向过程的语言中是默认的绑定方式。
在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限定调用父类方法,那么将直接在实际类型的父类的表中查找)
- 下面是
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》
Java多态之动态绑定的更多相关文章
- [Java学习] Java多态和动态绑定
在Java中,父类的变量可以引用父类的实例,也可以引用子类的实例. 请读者先看一段代码: 1. public class Demo { 2. public static void main(Strin ...
- Java多态和动态绑定是如何实现的
最近深入学习java,看到了动态绑定和多态这一章节,但遗憾的是,大部分的相关文章都停留于表面文字的描述.不得已,最后google了几篇英文文章,在此总结下这个问题. 一.静态绑定和动态绑定的区别 在J ...
- 《Java基础知识》Java多态和动态绑定
在Java中,父类的变量可以引用父类的实例,也可以引用子类的实例. 请读者先看一段代码: public class Demo { public static void main(String[] ar ...
- java 多态(动态绑定)
一.面向对象最核心的机制--动态绑定,也叫多态 1.1.通过下面的例子理解动态绑定,即多态 1 package javastudy.summary; 2 3 class Animal { 4 /** ...
- java基础疑难点总结之成员变量的继承,方法重载与重写的区别,多态与动态绑定
1.成员变量的继承 1.1要点 子类用extends关键字继承父类.子类中可以提供新的方法覆盖父类中的方法.子类中的方法不能直接访问父类中的私有域,子类可以用super关键字调用父类中的方法.在子类中 ...
- Java多态与反射
多态通过分离做什么和怎么做,从另一个角度将接口与实现分离开来:通过多态来消除类型之间的耦合关系,在Java中,多态也叫动态绑定,后期绑定或运行时绑定,那么什么是方法绑定? 方法调用绑定: 将一个方法与 ...
- Java 多态——与C++的比较
学习了Java和C++之后,由于长期不使用C++,而java的基础知识掌握不牢,现在已经搞不清java多态了.现在先来谈谈java多态,稍后有时间再更新C++的多态,并进行比较~ 一. Java的多态 ...
- C++和java多态的区别
C++和java多态的区别 分类: Java2015-06-04 21:38 2人阅读 评论(0) 收藏 举报 转载自:http://www.cnblogs.com/plmnko/archive ...
- Java静态绑定与动态绑定
程序绑定的概念: 绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来.对java来说,绑定分为静态绑定和动态绑定:或者叫做前期绑定和后期绑定. 静态绑定: 在程序执行前方法已经被绑定(也就是说 ...
随机推荐
- Maven系列第8篇:你的maven项目构建太慢了,我实在看不下去,带你一起磨刀!!多数使用maven的人都经常想要的一种功能,但是大多数人都不知道如何使用!!!
maven系列目标:从入门开始开始掌握一个高级开发所需要的maven技能. 这是maven系列第8篇. 整个maven系列的内容前后是有依赖的,如果之前没有接触过maven,建议从第一篇看起,本文尾部 ...
- pat 1120 Friend Numbers(20 分)
1120 Friend Numbers(20 分) Two integers are called "friend numbers" if they share the same ...
- hdu 1028 Sample Ignatius and the Princess III (母函数)
Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K ...
- H5 - css3(学习c3的第一天)
css3 中的转换:可以对元素进行移动.缩放.装懂.拉长或拉伸. 属性值:transform 每个浏览器的内核都不同,所以对应的前缀也不同,谷歌的是: -webkit- : ie的是 -ms- ...
- 痞子衡嵌入式:飞思卡尔Kinetis系列MCU启动那些事(10)- KBOOT特性(可靠升级)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔Kinetis系列MCU的KBOOT之可靠升级(Reliable Update)特性. 所谓可靠升级机制,即在更新Applica ...
- 初识JVM内存模型
计算机内存模型 在程序运行时,CPU通过访问主存获取数据,但随着CPU的快速发展,CPU访问速度越来越高,硬件无法满足CPU的条件下,大多内存加入了高速缓存机制,不同CPU都有对应的多级(一般为三)缓 ...
- AsyncDisplayKit编译和使用注意事项
Facebook开源框架,在github上可下载到.首先要编译AsyncDisplayKit库项目,有可能会出现下面错误: cocoaPods是基于ruby的项目版本控制软件,如果是ruby新手就会不 ...
- Java多线程——多线程方法详解
本系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线程的深入剖 ...
- python_day03
今日所学内容 1.函数部分: #函数的三种定义方式#1.无参函数:不需要外部传入的参数#2.有参函数:需要接受外部传入的参数#3.空函数:def func(): pass#pass代表说明都不用做# ...
- 老男孩 python 自学 打印05 dict 复习总结
dict 语法 {key : value} key 必须是可hash的 可哈希的目前有int . str . tuple .bool value 是没有任何限制的 2. 字典的相关操作 增 ...