關(guān)于this和super又必要理解清楚的地方!重要的,多態(tài)的關(guān)鍵
二話不說(shuō),先來(lái)一段代碼,比較短,需要付出一點(diǎn)點(diǎn)耐心(估計(jì)一上來(lái)就是代碼,又會(huì)趕走很多人吧.....)
//父類
class FatherClass {
public int value;
public void f() {
this.run();//注意這兒的是this,注意
}
public void run(){
System.out.println("FatherClass.run():"+this.value);
}
}
//子類
class ChildClass extends FatherClass {
public int value = 100;
public void ff() {
super.run();//注意這兒的是super,注意
}
//重寫
public void run(){
System.out.println("ChildClass.run():"+super.value);
}
}
//孫子類,這兒用了一個(gè)拼音,偷懶一下,記不到那個(gè)孫子的單詞了。寒啊...當(dāng)初還過四級(jí),現(xiàn)在忘光光
class SunziClass extends ChildClass {
public int value = 200;
//再次重寫
public void run() {
System.out.println("SunziClass.run():"+super.value);
}
}
//這兒是調(diào)用的Main
public class TestInherit {
public static void main(String[] args) {
FatherClass fc = new ChildClass();
fc.f();
FatherClass fc1 = new SunziClass();
fc1.f();
ChildClass cc = new SunziClass();
cc.ff();
}
}
想一想運(yùn)行結(jié)果,注意那個(gè)this和super。有點(diǎn)暈頭把,不要暈,穩(wěn)住!自己想一下結(jié)果,然后再來(lái)看運(yùn)行結(jié)果。
運(yùn)行結(jié)果如下:
ChildClass.run():0;
SunziClass.run():100;
FatherClass.run():0;
估計(jì)有不少人會(huì)大吃一驚!其他不吃驚的人可以散了!吃驚的人繼續(xù)看下面的。
this代表什么?這兒代表New出來(lái)的那個(gè)玩意兒在堆空間的引用地址
對(duì)于下面的這一句:
FatherClass fc1 = new SunziClass();
fc1這個(gè)變量里面放的就是this,是new SunziClass()這個(gè)玩意兒在堆空間的引用地址.
只是這兒fc1是定義成FatherClass,只有FatherClass的屬性和方法是可見的,不過這不是本文討論的重點(diǎn).
所以說(shuō)在父類里面寫的this其實(shí)就是這個(gè)父類或者他的子類,孫子類,曾孫子類... 在運(yùn)行的時(shí)候[重復(fù)一次哈,運(yùn)行的時(shí)候runtime], New 子類()或者New 孫子類()或者New 曾子類()或者....的堆空間的引用地址.
[再重復(fù)一次,FatherClass里面的this,子類里面的this...都是一樣的,指向New出來(lái)的那玩意兒的引用地址]
很神奇哈!!嘿嘿,這個(gè)其實(shí)就是 多態(tài)的體現(xiàn),也是多態(tài)的實(shí)現(xiàn)基礎(chǔ).看父類或者接口定義了方法調(diào)用的邏輯,子類可以根據(jù)需要改變算法! 這樣就可以將關(guān)注的方面分為兩個(gè)層面,一:關(guān)注方法調(diào)用的業(yè)務(wù)邏輯[做什么],二:關(guān)注方法的實(shí)現(xiàn)[怎么做]. "做什么和怎么做",這玩意兒好像在軟件工程里面比較眼熟哦!!!!
問題分解了,而且可復(fù)用性也大大提高了.
好了,this總結(jié)完了,好像越說(shuō)越暈了... 再穩(wěn)一下,看看Super
下面再來(lái)說(shuō)super
說(shuō)之前,分析一下內(nèi)存多,這個(gè)圖,挖卡,蜘蛛網(wǎng)來(lái)也....

現(xiàn)在看這兩句:
ChildClass cc = new SunziClass();
cc.ff();
這兒SunziClass里面沒有重寫父類ChildClass的ff方法,
所以是執(zhí)行的父類ChildClass的ff方法.這個(gè)方法里面有一個(gè)super.Run();
這兒實(shí)際上就執(zhí)行到了FatherClass的Run()方法.
這說(shuō)明什么啦.
說(shuō)明super只是記錄對(duì)象內(nèi)部的父類的特征(屬性和方法)的一個(gè)引用
(注意哈:這兒super不是指向父類對(duì)象的引用地址哈,new出來(lái)的玩意兒才在堆里面分配空間有引用地址,這兒沒有去new一個(gè)父類對(duì)象哈,只是執(zhí)行了父類的構(gòu)造函數(shù)將父類的特征生成了,但是屬于New出來(lái)的那個(gè)子類對(duì)象)
估計(jì)上面這段話也夠暈人了...
實(shí)踐一下,你可以寫
public FatherClass getThis()
{
return this;
}
編譯通過,沒有任何問題
但是你寫
public FatherClass getSuper()
{
return super;
}
嘿嘿,編譯出錯(cuò)! 為什么啦,
因?yàn)閟uper并不是一個(gè)堆空間里面的一個(gè)對(duì)象的引用地址,而this才是堆空間里面的一個(gè)對(duì)象的引用地址
super只能在對(duì)象內(nèi)部使用,而this可以在對(duì)象內(nèi)部使用也可以返回出對(duì)象外.
super是死的,編譯的時(shí)候就定死了super的指向了,而this是活的,在運(yùn)行時(shí)候決定其指向.
再說(shuō)一下,子類實(shí)例化對(duì)象,并沒有去實(shí)例化他的父類對(duì)象,也就是說(shuō),那個(gè)子類對(duì)象里面并沒有一個(gè)父類對(duì)象,
那你說(shuō)沒有父類對(duì)象,為什么子類構(gòu)造函數(shù)要執(zhí)行父類的構(gòu)造函數(shù)啦,那是因?yàn)樾枰獎(jiǎng)?chuàng)建父類的特征賦予子類,但是是由子類所有,而super就是用來(lái)區(qū)別是是否是父類對(duì)象的特征的.
重寫父類方法屬性,就是再創(chuàng)建了一個(gè)子類的特征,當(dāng)你用this的時(shí)候,就覆蓋了父類的特征了,但是父類特征還在那兒,用super就能訪問道,但是只能在對(duì)象的內(nèi)部使用.對(duì)象外面就只能看到覆蓋了父類特征的子類特征了.
寫完收工,我Cao,寫了2個(gè)小時(shí).....
其實(shí)寫了這么一大堆,就是一句:"this是當(dāng)前對(duì)象在堆空間的引用地址,super是當(dāng)前對(duì)象的父類特征的引用"
有什么不同的見解歡迎討論...共同進(jìn)步!!!