子类转为超类对象后,发生的成员方法以及成员变量的相关调用

首先,在学习JAVA的多态机制时,我们知道子类对象是可以向上自动转换为超类对象的,例如:

public class Father {
    public int a=0;
	public int b=2;
    public int getA() {
        return a;
    }
    public void print(){
        System.out.println("123");
    }
}
public class Son extends Father{
    public int a=1;
	public int c=3;
    public int getA(){
        return a;
    }
    public void pr(){
        System.out.println("456");
    }
}

Father t=new Son(); //该操作允许

然后,我们试着用该对象调用一些方法和变量:

		t.print();     //  123
        System.out.println(t.b);    //  2

发现该对象调用超类特有的方法和变量正常

		t.pr();    //   报错
        System.out.println(t.c);  //  报错

发现该对象不能调用子类特有的方法和变量

java核心技术里说,对象调用方法时,首先从该对象的方法表中找到名称一致的,再通过参数类型和个数确立方法。从上述结果来看,t对象并不能调用子类中特有的方法,所以对于这种对象,我的理解是:调用方法时应该编译器是从声明类型类的方法表中寻找,而不是实际类型类。没找到,就会报错。

然后,我们再做个实验

        System.out.println(t.getA());  //  1
        System.out.println(t.a);     //    0

该对象的getA方法和a变量是超类和子类都有的,发生了覆盖。
当t调用getA方法时结果为1,而超类中的getA方法应该是返回0的,说明此时t对象调用的getA方法属于子类。而对于a变量结果为0,说明此时t对象调用的变量a是超类的。按理说,是从声明类型的方法表中寻找,应该都是调用的超类的方法才对,

其实呢,原因在于java中存在静态绑定和动态绑定,对于getA方法,的确会从声明类型中查找,但是实际运行时,java虚拟机会根据对象的实际类型来运行方法,这便是动态绑定。很显然,对于变量a,它是属于静态绑定的,不仅如此,对于final、static、private的方法都是属于静态绑定的。当然,动态绑定主要是指发生了方法覆盖的情况,例如print方法,超类中独有而没被子类覆盖,调用时肯定是超类的。

到此,我们针对子类转换来的父类对象,可以总结一下:

  • 该对象不能调用子类中独有的方法和变量,只能调用声明类型方法表中的方法和变量
  • 该对象调用方法时会发生动态绑定,根据对象实际类型从而运行方法,主要针对发生了覆盖的方法
  • 该对象调用成员变量以及final、static、private的方法时,发生的是静态绑定
    • 对于成员变量,t对象调用的即是声明类型Father类中的变量a,该变量可以是Father自己声明,也可以是继承得来,也可以发生覆盖。
    • final、static、private方法很好理解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值