欢迎进入Java社区论坛,与200万技术人员互动交流 >>进入
4、关于父子实例的内存控制
(一般情况下是不用内部类来验证的,但是都是一样的啦,我偷懒下,所以使用了内部类,大家原谅哈)
1)当子类重写父类方法后,父类表面上只是调用属于自己的被子类重写的方法。
- publicclassTest{ classBase{ Base(){ this.info(); } publicvoidinfo(){ System.out.println(“Base”); } publicvoidgetInfo(){ info(); } } publicclassChildextendsBase{ @Override publicvoidinfo(){ System.out.println(“Child”); } } publicstaticvoidmain(String[]args){ Testtest=newTest(); Basebase=test.newChild(); base.info(); base.getInfo(); } }
运行结果:
2)上述是属于多态中方法的体现,但是方法有多态,实例变量无多态。
解释下“方法有多态,变量无多态”这句话:意思是,不管怎样,父类表面上只是调用属于自己的被子类重写的方法。而变量不一样,假设父类和子类都有同一个变量名的实例变量,向上转型后,通过父类访问的实例变量得到的值是自身的而非子类的。向下转型后,通过子类访问的实例变量得到的值是自身的而非父类的。
很多书上或教学视频上都讲,创建一个子类对象的时候,Java 会顺着继承结构往上一直找到 Object,然后从 Object 开始往下依次执行构造函数。先执行父类的构造函数,然后在其子类中会创建一个成员变量指向他的父类。其实这个说法是错误的,系统并不会真正的去创建父类对象,只是在子类对象中不仅保存了本身的实例变量,还有它父类的全部实例变量。
- publicclassTest{ classBase{//父类 inti=2; } publicclassChildextendsBase{//子类 inti=20; } publicstaticvoidmain(String[]args){ Testtest=newTest(); Childchild=test.newChild(); Basebase=child; System.out.println(“Base.i:”+base.i); System.out.println(“Child.i:”+child.i); } }
运行结果:
5、final修饰符
final变来那个在编译时就被确定下来了,相当于一个直接量。
1)final修饰的实例变量赋值时机:
定义final实例变量时 指定初始值
在非静态初始化模块中为final实例变量指定的初始值
在构造器中为final实例变量指定初始值
2)final修饰的类变量赋值时机:
定义final类变量时指定初始值
在静态初始化模块中为final实例变量指定的初始值
[1][2]
人的不幸缘于欲望,所以知足者长乐。