[转载]Java中的静态绑定和动态绑定
2016-08-22 11:21
295 查看
Java中的静态绑定和动态绑定
2014/12/29 | 分类: 基础技术 | 0条评论 | 标签: JAVA, 动态绑定, 静态绑定
分享到:17
原文出处: androidyue
一个Java程序的执行要经过编译和执行(解释)这两个步骤,同时Java又是面向对象的编程语言。当子类和父类存在同一个方法,子类重写了父类的方法,程序在运行时调用方法是调用父类的方法还是子类的重写方法呢,这应该是我们在初学Java时遇到的问题。这里首先我们将确定这种调用何种方法实现或者变量的操作叫做绑定。
在Java中存在两种绑定方式,一种为静态绑定,又称作早期绑定。另一种就是动态绑定,亦称为后期绑定。
区别对比
静态绑定发生在编译时期,动态绑定发生在运行时使用private或static或final修饰的变量或者方法,使用静态绑定。而虚方法(可以被子类重写的方法)则会根据运行时的对象进行动态绑定。
静态绑定使用类信息来完成,而动态绑定则需要使用对象信息来完成。
重载(Overload)的方法使用静态绑定完成,而重写(Override)的方法则使用动态绑定完成。
重载方法的示例
这里展示一个重载方法的示例。
验证
光看表象无法证明是进行了静态绑定,使用javap发编译一下即可验证。18: invokevirtual #6 // Method TestMain$Caller.call:(Ljava/lang/String;)V
确实是发生了静态绑定,确定了调用了接收String对象作为参数的caller方法。
重写方法的示例
验证
使用javap不能直接验证动态绑定,然后如果证明没有进行静态绑定,那么就说明进行了动态绑定。18: invokevirtual #6 // Method TestMain$Caller.call:(Ljava/lang/String;)V
这里是
TestMain$Caller.call而非
TestMain$SubCaller.call,因为编译期无法确定调用子类还是父类的实现,所以只能丢给运行时的动态绑定来处理。
当重载遇上重写
下面的例子有点变态哈,Caller类中存在call方法的两种重载,更复杂的是SubCaller集成Caller并且重写了这两个方法。其实这种情况是上面两种情况的复合情况。下面的代码首先会发生静态绑定,确定调用参数为String对象的call方法,然后在运行时进行动态绑定确定执行子类还是父类的call实现。
验证
由于上面已经介绍,这里只贴一下反编译结果啦
好奇问题
非动态绑定不可么?
其实理论上,某些方法的绑定也可以由静态绑定实现。比如但是为什么没有进行静态绑定呢?
假设我们的Caller继承自某一个框架的BaseCaller类,其实现了call方法,而BaseCaller继承自SuperCaller。SuperCaller中对call方法也进行了实现。
假设某框架1.0中的BaseCaller和SuperCaller
然后我们再次假设这个框架1.1版本中BaseCaller不重写SuperCaller的call方法,那么上面的假设可以静态绑定的call实现在1.1版本就会出现问题,因为在1.1版本上super.call应该是使用SuperCall的call方法实现,而非假设使用静态绑定确定的BaseCaller的call方法实现。
所以,有些实际可以静态绑定的,考虑到安全和一致性,就索性都进行了动态绑定。
得到的优化启示?
由于动态绑定需要在运行时确定执行哪个版本的方法实现或者变量,比起静态绑定起来要耗时。所以在不影响整体设计,我们可以考虑将方法或者变量使用private,static或者final进行修饰。
相关文章推荐
- Java面试系列【动态绑定、静态绑定】-动态绑定,基础篇
- Java【动态绑定、静态绑定】-动态绑定
- Java中的静态绑定和动态绑定
- 【Java学习笔记】继承,动态绑定与静态绑定
- Java的多态(静态绑定和动态绑定)
- Java中的静态绑定和动态绑定
- java静态绑定和动态绑定
- JAVA中的静态绑定和动态绑定
- Java静态绑定和动态绑定
- Java静态绑定与动态绑定
- JAVA-动态绑定和静态绑定
- Java中的重载、重写、多态,静态绑定、动态绑定
- java 动态绑定和静态绑定例子分析
- Java之重载,隐藏,静态绑定,动态绑定
- Java静态绑定与动态绑定
- 详细解释JAVA中的静态绑定和动态绑定
- java静态绑定和动态绑定(转载)
- java 动态绑定与静态绑定
- java静态绑定和动态绑定
- Java 静态绑定和动态绑定