Java调用对象的方法时,有两种机制,一种是静态绑定,一种是动态绑定
绑定:一个方法的调用与调用这个方法的类连接在一起的过程被称为绑定。
静态绑定
概念:在程序运行前,也就是编译时期JVM就能够确定方法由哪类对象调用(注意和多态的向上转型中子类方法的调用规则区别开),这种机制称为静态绑定。如果一个方法不可被继承,或者继承后不能被覆盖,(由private、final、static 所修饰的方法和构造方法)那么它就是静态绑定,因为编译后可以确定具体是调用的哪个方法。
动态绑定
概念:除了由private、final、static 所修饰的方法和构造方法外,Java虚拟机在运行期间决定方法由哪个对象调用的过程称为动态绑定。
动态绑定具体表现为:
- 当调用对象方法的时候,该方法会和该对象的运行类型(内存地址)绑定。
- 当调用对象属性时,没有动态绑定机制,不会和运行类型绑定,哪里声明哪里使用。
代码示例
public class DynamicBinding {
public static void main(String[] args) {
//编译类型 A, 运行类型 B,向上转型
//在编写 A a = new B();的时候,编译器并不知道a对象真正引用的是谁,
//在程序运行时期才知道,这个a是一个A类的对象,但是却指向了B的引用
//所以要在运行时才能进行绑定的过程
A a = new B();
//sum()不是子类独有的方法,父类中有,因此可以调用,但是按照多态规则,子类调用方法从运行类型开始找
System.out.println(a.sum());//30,从运行类型B找,没有,按照继承调用规则,找父类A,有,执行
//遇到getI()函数,按照动态绑定规则,该函数和运行类型B绑定,
//调用B的getI()
System.out.println(a.sum1());//20,从运行类型B找,没有,按照继承调用规则,找父类A,有,执行
//对象的属性没有动态绑定机制,故使用父类A中的值i=10
}
}
class A {//父类
public int i = 10;
//动态绑定机制:
public int sum() {//父类 sum()
return this.getI() + 10;//20 + 10
}
public int sum1() {//父类 sum1()
return this.i + 10;//10 + 10
}
public int getI() {//父类 getI
return i;
}
}
class B extends A {//子类
public int i = 20;
public int getI() {//子类 getI()
return i;
}
}