朝花夕拾——this和super到底是引用还是对象?

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实际上并不是对象,一定程度是可以看做是父类的引用(因为无法调用被重写的方法),记住只是引用而已。




  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值