Static Binding versus Dynamic Binding

所谓“绑定(binding)”,是指建立method call(函数调用)和method body(函数本体)的关联。一切方法调用(method call)在Class文件中存储的都是一个常量池中的符号引用,而不是方法在实际运行时内存布局中的入口地址(也就是直接引用)。分为前期绑定和后期绑定。

1)前期绑定(Early Binding):在程序运行之前绑定,由编译器和连接程序实现,又叫静态绑定(Static Binding)。在类加载的解析阶段,会将其中的一部分符号引用转换为可确定的直接引用,不会延迟到运行期再去完成。前提是这些方法要“编译器可知,运行期间不变”,也就是方法在程序真正运行之前就有一个可确定调用的版本,并且这个方法的调用版本在运行期间是不可改变的。
      主要包括静态方法和私有方法两大类,前者直接与类型相关,后者在外部不可被访问,这两种方法都不可能通过继承或者别的方式重写出其他版本,因此适合在类加载阶段进行解析。

A: class methods are always statically bound(methods those declared with static modifier ). 静态方法不会参与多态和动态绑定,因为静态方法作用在类级别而不是作用到具体的对象。Polymorphism requires an object, because it enables a method to be dynamically selected  based on the actual class of the object. Thus,polymorphism doesn't apply to class mtehods. If you invoke a class method on an object, the implementation of the class method is chosen not based on the class of the object at run-time, but on the type of the object reference at compile-time.
   静态方法对应的方法调用字节码指令是invokestatic.

B: Static binding of instance methods: 
  i: 私有方法: private methods(because java compiler precisely know the method to be invoked is in the same class),
  ii: 父类方法(super调用): methods invoked with super keyword(parent class),
  iii: 构造函数 instance initialization methods(constructor, this special kind of method is invoked only when an object is created)
  这三种方法对应的方法调用字节码指令是invokespecial

C: final方法
   通过invokevirtual指令来调用,但是由于无法被覆盖,没有其他版本,所以无法对方法接受者进行多态选择,又或者说多态选择的结果是唯一的。final修饰的方法是非虚方法。


以上情况都属于非虚方法,非虚方法在类加载静态解析时进行绑定,非虚方法包括:通过invokestatic和invokespecial字节码指令调用的方法,以及通过invokevirtual调用的final方法。

2)后期绑定(Late Binding):如果绑定动作在程序执行期根据对象的类型进行绑定,由方法调用机制实现,因此又叫做动态绑定(Dynamic Binding),或者运行时绑定(Run-time Binding)。


Exception for three special cases mentioned above, all instance methods in Java programs are dynamically bound. The instance method that is invoked at run-time will be determined by the actual class of the object, not by the type of the reference.

虚方法包括:通过invokevirtual和invokeinterface字节码指令调用的方法(除了final)。

invokevirtual:调用所有的虚方法
invokeinterface:调用接口方法,会在运行时再确定一个实现此接口的对象。

分派:定位方法执行版本
      分配与解析二者不是不二选一的排他关系,而是在不同层次上筛选和确定目标的过程。比如静态方法会在类加载时期就进行解析,而静态方法显然也是可以拥有重载版本的,选择重载版本的过程是通过静态分派来完成的。

1)静态分派:所有依赖静态类型(Static Type)或者外观类型(Apparent Type)来定位方法执行版本的分派动作,都成为静态分派。静态分派选择方法目标版本时不仅要考虑方法的接受者(Receiver),也考虑方法的参数(数量、类型、顺序)。典型应用是方法重载。
      编译期完成。

2)动态分派:由于编译期已经决定了目标方法的方法签名(Signature),因此此时参数的外观类型还是实际类型都不会对方法的选择造成任何影响,唯一可以影响虚拟机选择的因素只有该方法的接收者的实际类型。典型应用是Override.


非虚方法一定是静态分派的。
虚方法会经历静态分派和动态分派
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值