1. 程式人生 > >深入理解Java中super關鍵字

深入理解Java中super關鍵字

之前一直以為super和this是相同的,this指代子類當前物件,super指代父類物件。之前與實驗室師兄還談論過這個問題,當時他說的super只是Java中一個關鍵字,與this並不相同。一直有疑惑,覺得下面這篇部落格分析的比較到位。

 Java中關鍵字 super表示的真正物件
    java中的super,大家都知道是表示一個父類的引用。上次群裡見到一個網友詢問 super.getClass().getName()的輸出問題,大部分都知道輸出的是當前這個類的類名。而不是父類的名稱。關於這個問題的解釋很多,基本都是說getClass()是一個final方法,說這個方法都是呼叫超父類Object的方法。這個解釋很好,也容易理解,不過,我們從super這個關鍵詞的本質入手,就能更清楚,為什麼super.getClass().getName()會輸出當前類的名稱了。

先定義兩個類,一個父類,一個繼承的子類。

父類:

public class Parent {  
    public String name;  
    private int code;  
    public Parent parent;  
    //定義幾個父類成員屬性,parent將指向this父類物件  
    public Parent()  
    {  
        //parent指向this,就是當前例項的父類物件,並輸出hashcode和給code屬性賦值  
        parent=this;  
        code=1001;  
        System.out.println("Parent's code is:"+code);  
        System.out.println("Parent hashcode is:"+this.hashCode());  
    }  
    //定義一個過載的構造方法,用於測試使用了哪個父類構造方法  
    public Parent(String name){  
        parent=this;  
        this.name=name;  
        System.out.println("Parent's name is"+name);  
        code=1002;  
        System.out.println("Parent's code is"+code);  
  
        System.out.println("Parent hashcode is:"+this.hashCode());  
    }  
    public int getCode()  
    {  
        //列印父類code屬性值,  
        System.out.println("Parent :print code :"+code);  
        return code;  
    }  
}  
子類:
public class Child extends Parent{  
    public String childName;  
    private int childCode;  
    //定義兩個類的不同修飾符的屬性  
    public Child(String childName)  
    {  
        //給屬性賦值  
        this.childName=childName;  
        //輸出屬性值,和類的hashcode值  
        System.out.println("child's childName is:"+childName);  
        System.out.println("child hashcode is:"+this.hashCode());  
    }  
    //測試方法  
    public void test()  
    {  
        //通過super獲取父類中的parent,這個成員就表示了父類物件。  
        Child testChild=(Child)super.parent;  
        //強轉parent為子類型別。並輸出子類中定義的屬性,和獲取父類getCode()方法  
        System.out.println("testChild name is:"+testChild.childName);  
        testChild.getCode();  
    }  
    public static void main(String[] args) {  
        //例項化  
        Child c=new Child("window");  
        c.test();  
    }  
}  

執行結果:

Parent's code is:1001
Parent hashcode is:366712642
child's childName is:window
child hashcode is:366712642
testChild name is:window
Parent :print code :1001

 Parent's code is:1001
 //表示執行了父類預設的構造器。其實在子類的構造器中,只要沒有顯示呼叫this和super,都會預設呼叫父類無參構造器,即:super(); Parent
 hashcode is:366712642 
 //這裡是父類物件的雜湊值
 child's childName is:window 
 //呼叫子類的構造方法,輸出childName和hashcode碼值,大家可以看到,父類的this物件和子類例項的物件,hashcode碼是相同的。
 child hashcode is:366712642
 * //這裡執行test()方法的結果。
 //使用Child testChild=(Child)super.parent 強制轉換父類中指向父類this物件的parent物件為子類Child物件,並輸出子類childName屬性值。
 testChild name is:window
 //輸出結果上可以看出,這個parent其實就是子類的例項物件。應該說記憶體中的物件是同一個,只是不同的表示方式。
 //執行testChild.getCode(); 呼叫父類的getCode()方法,輸出的和父類構造方法中的code值是相同的。
 Parent :print code :1001

從上面可以看出super這個關鍵字所表示的引用父類物件,其實和當前例項化的子類物件在記憶體中是同一個物件,雖然不知道sun 的虛擬機器是如何實現這個關鍵字的,但是這個super的等同效果就是(Parent)this,這裡的this是當前代表當前例項化的子類物件。

通過在父類中新增一個Parent型別的成員,來指向父類例項化的那個this物件,達到引用父類物件的目的,使用super.parent來獲得父類parent物件的引用。

執行的結果表明,這個parent應用的其實就是當前子類例項物件,通過強制轉換為子類型別,這個父類Parent型別的parent也可以讀取成員childName屬性值。就表明了他們在記憶體中是同一個物件。而且他們的hashcode值也是相同的。

java說明中指出,super是代表父類物件的引用,而super()表示應用父類的預設構造方法,看起來這個super和c中的define有點相同作用的效果。在這個例子中,super代表的父類物件的引用,和父類中parent代表的都是父類物件的引用,parent其實就是當前記憶體中子類物件的引用,如同(Parent)this一樣,這樣就可以解釋為什麼使用(Child)super.parent可以得到子類成員childName。

回到開始的問題,super.getClass().getName(),這樣,就很容易解釋他為什麼是輸出當前類的名稱了,因為構造一個例項化物件,其中,在父類和子類構造方法中,引用的物件都是同一個,都是當前例項化的子類物件。super關鍵字應該充當了一個型別轉化的作用。

熟悉c的知道,c中經常使用強制轉換指標型別來引用一些結構或變數的部分資料,如通過強制轉換為不同結構型別,來引用不同資料大小的結構體。這裡的應用效果應該等同,通過(Parent)Child可以通過轉換為父類型別而只引用父類型別的那一部分資料。

javanew一個物件,和cc++這些和記憶體打交道的語言一樣,都是會分配記憶體,在c中可能更直觀一點,我們在此不討論到底是分配了多大的記憶體問題。

new一個子類的時候,上面例子看到,父類的成員同樣也有賦值初始化,說明,同樣在記憶體中也有儲存父類的資訊空間,(Object類的不討論)。

一個抽象點的圖:



可能圖表達不對,大概就是這個意思

-----------------------------------------------------------------JacobGo!--------------------------------------------------------------------------

本文轉載自:http://blog.csdn.net/sujudz/article/details/8034770