1. 程式人生 > >關於this和super的區別(轉載)

關於this和super的區別(轉載)

先看下面一段程式碼,比較短,

//父類
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); 字串6

    }
}

//孫子類,這兒用了一個拼音,偷懶一下,記不到那個孫子的單詞了。寒啊...當初還過四級,現在忘光光
class SunziClass extends ChildClass {
    public int value = 200;
    //再次重寫
    public void run() {
        System.out.println("SunziClass.run():"+super.value);
    }
}

//這兒是呼叫的Main
public class TestInherit {
      public static void main(String[] args) {
                FatherClass fc = new ChildClass();
                fc.f();
                FatherClass fc1 = new SunziClass();
                fc1.f();
字串1
                ChildClass cc = new SunziClass();
                cc.ff();
     }
}

想一想執行結果,注意那個this和super。有點暈頭把,不要暈,穩住!自己想一下結果,然後再來看執行結果。

執行結果如下:
ChildClass.run():0;
SunziClass.run():100;
FatherClass.run():0;

估計有不少人會大吃一驚!其他不吃驚的人可以散了!吃驚的人繼續看下面的。

this代表什麼?這兒代表New出來的那個玩意兒在堆空間的引用地址
對於下面的這一句:
FatherClass fc1 = new SunziClass();
fc1這個變數裡面放的就是this,是new SunziClass()這個玩意兒在堆空間的引用地址.
只是這兒fc1是定義成FatherClass,只有FatherClass的屬性和方法是可見的,不過這不是本文討論的重點.

所以說在父類裡面寫的this其實就是這個父類或者他的子類,孫子類,曾孫子類... 在執行的時候[重複一次哈,執行的時候runtime], New 子類()或者New 孫子類()或者New 曾子類()或者....的堆空間的引用地址.

字串4


[再重複一次,FatherClass裡面的this,子類裡面的this...都是一樣的,指向New出來的那玩意兒的引用地址]

很 神奇哈!!嘿嘿,這個其實就是多型的體現,也是多型的實現基礎.看父類或者介面定義了方法呼叫的邏輯,子類可以根據需要改變演算法! 這樣就可以將關注的方面分為兩個層面,一:關注方法呼叫的業務邏輯[做什麼],二:關注方法的實現[怎麼做].  "做什麼和怎麼做",這玩意兒好像在軟 件工程裡面比較眼熟哦!!!!

問題分解了,而且可複用性也大大提高了.

好了,this總結完了,好像越說越暈了... 再穩一下,看看Super

下面再來說super
說之前,分析一下記憶體多,這個圖,挖卡,蜘蛛網來也....


字串2



現在看這兩句:
ChildClass cc = new SunziClass();
cc.ff();
這兒SunziClass裡面沒有重寫父類ChildClass的ff方法,
所以是執行的父類ChildClass的ff方法.這個方法裡面有一個super.Run();
這兒實際上就執行到了FatherClass的Run()方法.

這說明什麼啦.
說明super只是記錄物件內部的父類的特徵(屬性和方法)的一個引用
(注意哈:這兒super不是指向父類物件的引用地址哈,new出來的玩意兒才在堆裡面分配空間有引用地址,這兒沒有去new一個父類物件哈,只是執行了父類的建構函式將父類的特徵生成了,但是屬於New出來的那個子類物件)
估計上面這段話也夠暈人了...

實踐一下,你可以寫
public FatherClass getThis()
{
    return this;
}
編譯通過,沒有任何問題
但是你寫
public FatherClass getSuper()
{
    return super; 字串3
}

嘿嘿,編譯出錯! 為什麼啦,
因為super並不是一個堆空間裡面的一個物件的引用地址,而this才是堆空間裡面的一個物件的引用地址
    super只能在物件內部使用,而this可以在物件內部使用也可以返回出物件外.
    super是死的,編譯的時候就定死了super的指向了,而this是活的,在執行時候決定其指向.

再說一下,子類例項化物件,並沒有去例項化他的父類物件,也就是說,那個子類物件裡面並沒有一個父類物件,
那你說沒有父類物件,為什麼子類建構函式要執行父類的建構函式啦,那是因為需要建立父類的特徵賦予子類,但是是由子類所有,而super就是用來區別是是否是父類物件的特徵的.
重寫父類方法屬性,就是再建立了一個子類的特徵,當你用this的時候,就覆蓋了父類的特徵了,但是父類特徵還在那兒,用super就能訪問道,但是隻能在物件的內部使用.物件外面就只能看到覆蓋了父類特徵的子類特徵了.

字串1



其實就是一句:"this是當前物件在堆空間的引用地址,super是當前物件的父類特徵的引用"