Java构造器在初始化的构成中经常会使用到this和super关键词,那么他们到底是特定类的引用还是对象呢?下面我们逐步看清他们的真实面目。
先看例子1——这个this到底是什么类型,又是谁的对象?
package java_zhaohuaxishi; class Father{ private String name = "父亲"; public Father(){ this.play(); System.out.println(this.name); } public void play(){ System.out.println("父亲在玩耍!"); } } class Son extends Father{ private String name = "儿子"; public Son(){ this.play(); System.out.println(this.name); } public void play(){ System.out.println("儿子在玩耍!"); } } public class Example1 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub new Son(); } }我们创建一个Son对象,根据构造器初始化顺序,会在父类里面使用到this进行变量引用和方法调用,先看看打印结果:
儿子在玩耍! 父亲 儿子在玩耍! 儿子在执行Son构造器的时候,先执行父类构造器(事实上是会把父类构造器的内容拿到Son构造器里面),this调用了play方法,从输出中看到,调用的是Son的play方法而却使用了父类的变量!这让我们想到了java 的多态特性。如果B类集成A类,那么A b = new B(),b编译时是A的类型而运行时却变现B的特征。一般来说,调用实例变量,看的是该对象的编译时类型,而调用对象方法,看的是对象的运行时类型。
那么我们可以推出此时的this其实是一个Son对象但却是一个Father类型的引用。
例子2——super也是一个对象吗?
package java_zhaohuaxishi; class A{ public A getA(){ return this; } } class B extends A{ public A getSuper(){ return super.getA(); } } public class Example2 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub B b = new B(); <span style="white-space:pre"> </span>System.out.println(b.getClass()); <span style="white-space:pre"> </span>System.out.println(b.getSuper().getClass()); <span style="white-space:pre"> </span>System.out.println(b==b.getSuper());; } }我们假设super如果真的是父类类型的对象,那么b.getSuper返回来的应该是父类类型的对象,那么结果的第二行应该输出A且第三行应该输出false
我们看看打印结果:
class java_zhaohuaxishi.B class java_zhaohuaxishi.B true然而我们的假设是错的!super并不是一个对象!再进一步验证
package java_zhaohuaxishi; class C{ public C getC(){ return this; } } public class Example3 extends C{ //出现编译错误 public C getC(){ return super; } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub C c = new C(); } }我们可以return this却不能return super ,编译失败,再次验证了确实不是一个对象。那么我们回想下,之前为什么super.却能去调用行为方法呢?
实际上,当程序创建一个java子类对象的时候,系统不仅仅会在内存中为该类的实例变量分配内存,也会为该类的父类实例变量分配内存。那么就存在一种情况,子类中拥有和父类同名的变量,而系统并不会覆盖掉父类的同名变量,而是选择隐藏(依然需要分配内存)。当然,还存在父类的方法被子类覆盖重写,重写的方法也会被隐藏起来。那么如何调用这些被隐藏的父类变量和方法呢?答案就是“借助super.来引用”。
那么现在可以得出结论:
(1)this是真实存在的对象,而this的类型往往是看所在构造器所属的类;
(2)super实际上并不是对象,一定程度是可以看做是父类的引用(因为无法调用被重写的方法),记住只是引用而已。
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/u010794180/article/details/47109677