Java的动态绑定机制
B extends A
A a = new B();
对象a的编译类型为A,运行类型为B
在调用对象方法时,该方法会和该对象的内存地址/运行类型进行绑定
在调用对象属性时,没有动态绑定,哪里声明,哪里使用
对象a能调用A中的所有成员(受访问权限限制) 但a不能调用B中的特有的成员
因为a中的成员均是在编译时确定的,所以受编译类型A影响,只能调用A中含有的成员。
但是编译后运行时要看运行类型,所以在调用A和B中都存在的方法时,会调用B中的方法
如示例
public class DynamicBinding {
public static void main(String[] args) {
A a = new B();
System.out.println(a.sum());//输出30
System.out.println(a.sum1());//输出20
}
}
class A{
public int i=10;
public int sum(){
return getI()+10;
}
public int getI(){
return i;
}
public int sum1(){
return i+10;
}
}
class B extends A{
public int i=20;
public int x-30;
// public int sum(){
// return i+20;
// }
public int getI(){
return i;
}
//public int sum1(){
// return i+10;
// }
}
a.sum()先去找运行类型B中的sum方法,由于B中没有,则去找父类A中的sum方法,父类中sum方法返回了getI()方法,此时又去找运行类型中的getI()方法,getI()方法返回i,这个i是在B中声明的,所以为B中的i值20。将20返回到sum方法中,最后打印为30.
a.sum1()同样找到父类中的sum1()方法,返回的i是在A中声明的,所以i为10,最后打印20.
a.x调用失败,因为a不能调用运行类型B中的特有的成员,只能调用编译类型A中有的成员,这是在编译阶段决定的,编译后对象a中是不存在属性x的。
若是想调用B中特有的成员,则需要父类A向下转型成B 如: B b = (B) a;
此时对象b的编译类型和运行类型都是B类,所以可以调用B的所有成员,但向下转型有个前提条件,就是a原本指向的就是当前类型的对象 a=new B(),这样才能向下转型。