java中早期绑定和后期绑定的区别
Java中的绑定是指将方法或函数体与Java编译器的方法或函数调用相关联的过程。简单地说,当Java编译器调用一个函数时,正确定位相应函数的方法的任务就是绑定。根据编译器何时能够将方法体与其方法调用相关联,java中的绑定分为两个主要标头:
- 早期绑定,也称为静态绑定
- 后期绑定,也称为动态绑定
让我们详细介绍这两种类型。
早期绑定或静态绑定
如前所述,结合是指与其呼叫相关或者"结合"方法体的过程。
早期或者静态绑定是指Java编译器在编译时,这两个实体的关联。
静态绑定用于将任何私有,最终或者静态方法主体与其在发生的任何执行之前的方法调用语句相关联。
为什么早期绑定相关的静态最终和私有方法?
这是由于任何子类无法覆盖静态,最终或者私有方法,因此它们总是通过常量引用引用,例如:定义它们的类。
由于静态,最终或者私有方法的属性,Java编译器可以轻松确定预先执行,这些方法只能由它们定义的类的对象引用。
以下示例应展示静态绑定。
代码示例:
class Car { public static void startEngine(){ System.out.println("Car Engine Started"); } } public class Porsche extends Car { public static void startEngine(){ System.out.println("Porche's Engine Started"); } public static void main(String args[]){ Car car1 = new Porsche(); Car car2 = new Car(); car1.startEngine(); car2.startEngine(); } }
输出 :
Car Engine Started Car Engine Started
分析:
如果我们分析上述代码的输出,我们会注意到尽管在派生类保时捷的"Startengine"方法和初始化对象"Car1"中,但仍未覆盖方法"Startengine()"方法并打印超级汽车的文字。
这是由于类汽车的静态方法"Startengine()"无法被覆盖,并且在编译期间由Java编译器绑定。
现在让我们看看其他形式的绑定:
后期绑定或者动态绑定
如果编译器无法确定在编译期间绑定特定方法的调用,那么它率到后期绑定或者动态绑定。
动态绑定的最佳实例是方法覆盖。
子类覆盖超类和在执行期间的方法,方法与各自的引用相关联。
这里可以注意到,对于发生动态绑定,必须必须覆盖的方法未被声明为静态,最终或者私有。
声明使用上述任何修饰程序的方法将阻止其被覆盖,并且Java将求静态绑定,因为它可以轻松确定父参考。
让我们使用前一个示例观察动态绑定。
只有这一次,这些方法将不再被声明为"静态"
代码示例:
class Car { public void startEngine(){ System.out.println("Car Engine Started"); } } public class Porsche extends Car { public void startEngine(){ System.out.println("Porche's Engine Started"); } public static void main(String args[]){ Car car1 = new Porsche(); Car car2 = new Car(); car1.startEngine(); car2.startEngine(); } }
输出:
Porche's Engine Started Car Engine Started
分析:
输出的差异是明显的,因为第一个方法调用已成功绑定类保时捷的引用并称为覆盖方法"startengine()"。
由于我们不再使用静态关键字作为修饰符,因此Java编译器无法找到绑定方法在编译期间的引用,因此诉诸于动态绑定,并且在运行时确定方法的类型或者引用。
静态和动态绑定之间的差异
静止绑定 | 动态绑定 |
---|---|
静态或者早期绑定在编译时发生。 | 在运行时发生动态或者后期绑定 |
声明为private、static或final的方法在编译期间显示静态绑定,因为它们不能被重写并且可以关联; | 公共、受保护或默认的方法显示动态绑定,因为它们可以被重写,并且它们的引用仅在运行时关联 |
在早期绑定中不使用实际对象引用 | 使用实际对象引用 |
方法重载是静态或早期绑定的最佳示例; | 方法重写是动态或后期绑定的最佳示例 |