继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

变量的编译时类型和运行时类型

烙印99
关注TA
已关注
手记 391
粉丝 92
获赞 446

当变量的编译时类型和运行时类型不同时,通过该变量访问它引用的对象的实例变量时,该实例变量的值由声明该变量的类型决定。但通过该变量调用它引用的对象的实例方法时,该方法行为将由它实际所引用的对象来决定。

public class StudyVisitorSonVar {public static void main(String[] args) {new Cricle("圆形");}}class Shap{public String desc;public Shap() {//该变量访问它引用的对象的实例变量时,该实例变量的值由声明该变量的类型即Shap决定//通过该变量调用它引用的对象的实例方法时,该方法行为将由它实际所引用的对象即Cricle来决定this.desc = getDesc();}public String getDesc() {this.desc = "形状";System.out.println("Shap 父类的描述为:" + this.desc);return desc;}public void setDesc(String desc) {this.desc = desc;}}class Cricle extends Shap{public String desc;public Cricle(String desc) {this.desc = desc;}@Overridepublic String getDesc() {System.out.println("Cricle 子类的描述为:" + this.desc);return this.desc;}}运行结果为:Cricle 子类的描述为:null

之所以会出现这种结果是因为调用子类构造器前会隐式调用父类无参构造器,this.desc这个this虽然代表Cricle对象,但它却位于Shap构造器中,它的编译时类型是Shap,而它实际引用一个Cricle对象。

当变量的编译时类型和运行时类型不同时,通过该变量访问它引用的对象的实例变量时,该实例变量的值由声明该变量的类型决定,但通过该变量调用它引用的对象的实例方法时,该方法行为将由它实际所引用的对象来决定。这时候就会调用子类的getDesc()方法,因为子类的desc成员变量还没有被初始化所以输出结果为null。

所以需要注意如果父类构造器调用了被子类重写的方法,且通过子类构造器来创建子类对象,不管是显式还是隐式调用了这个父类构造器就会导致子类的重写方法在子类构造器的所有代码之前被执行,从而导致子类的重写方法访问不到子类的实例变量值的情形

原文出处

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP