Java基础 - 继承里的 隐藏 vs覆盖?
【重点】变量/方法:java继承里的 隐藏 vs方法
隐藏:父类和子类拥有相同名字的属性或者方法时,父类的同名的属性或者方法形式上不见了,实际是还是存在的。
- 变量隐藏:子类实例变量/静态变量可以隐藏父类的静态/实例变量,总结为“变量”可以交叉隐藏。
- 方法隐藏:只有一种形式,就是父类和子类存在相同的静态方法。
覆盖:子类重写父类的方法,要求方法名和参数类型完全一样(参数不能是子类),返回值和异常比父类小或者相同(即为父类的子类),访问修饰符比父类大或者相同。
- 变量覆盖:不存在
- 方法覆盖:子类实例方法-->[覆盖]-->父类实例方法;子类静态方法-->[覆盖]-->父类静态方法。总结为“方法”不能交叉覆盖。
【重点】定义:隐藏 vs 覆盖
- 被隐藏的属性,在子类被强制转换成父类后,访问的是父类中的属性
- 被覆盖的方法,在子类被强制转换成父类后,调用的还是子类自身的方法
- 因为覆盖是动态绑定,是受RTTI(run time type identification,运行时类型检查)约束的,隐藏不受RTTI约束,总结为RTTI只针对覆盖,不针对隐藏
例子(必看!)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class Parent{ int x= 10 ; public Parent(){ add( 2 ); } void add( int y){ x+=y; } } class Child extends Parent{ int x= 9 ; void add( int y){ x+=y; } public static void main(String[] args){ Parent p= new Child(); System.out.println(p.x); } } |
答案
1 | 答案应该是 10 |
在上面的试题中,子类Child的实例方法add(int y)覆盖了父类Parent的实例方法add(int y),而子类的实例变量x则是隐藏了父类的实例变量x。
Child对象的初始化过程是:
首先为父类的实例变量x分配内存空间,因为在定义变量x时为它赋了值(int x=10),所以会同时将这个值赋给x。
其次调用父类的无参构造函数,Parent的构造函数中做的唯一的事情就是调用了add(2);
第三、由于子类的add(int y)方法覆盖了父类的方法,所以add(2)实际调用的是子类的方法,在子类的add方法中做了如下操作x+=j;在这里由于子类的实例变量x隐藏了父类 的实例变量x,所以这条语句是针对子类本身的,但是这时还没有为子类的实力变量x分配空间,它的默认值是0,加2之后是2。
第四、父类初始化完毕后接着初始化子类,为子类的x分配内存空间并将它赋值为9,之前的add(2)操作白瞎了。
再次注意Parent p=new Child();这条语句,它是用父类的引用指向子类的对象,而前面已经说过变量只会被隐藏不会被覆盖,所以这时的p.x值应该是父类的10,而不是子类的9;
如果将输出语句换成下面的语句结果就是9了:
System.out..println(((Child)p).x); //首先将p转换成Child类型
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?