Java——父子實例的內存情況解析

衆所周知,在Java中,一個非final類可以被其他類所繼承,同時子類將擁有父類的實例變量和實例方法,而且子類還可以重寫父類中的方法。

但當子類中存在和父類同名的變量和方法時,分別用父類類型的變量、子類類型的變量去調用對象的實例變量和方法時,會有怎樣的結果呢?
我們不妨來做個試驗:

定義一個Base類(父類),在其中聲明一個實例變量和實例方法;同時定義一個Sub類(子類),在其中聲明與父類中相同的實例變量和方法(但是值和方法體不同)。

class Base{
    int count = 1;

    public void info() {
        System.out.println("base info ... ");
    }
}

class Sub extends Base{
    int count = 10;

    @Override
    public void info() {
        System.out.println("sub info ... ");
    }
}

public class Main {
    public static void main(String[] args) {
        Sub obj = new Sub();
        System.out.println(obj.count);
        obj.info();

        Base baseObj = obj;
        System.out.println(baseObj.count);
        baseObj.info();
    }
}

然後在main中聲明兩個變量:一個是Base類型的baseObj變量,另一個是Sub類型的obj變量。分別用這兩個變量調用count實例變量和info()方法,結果如下:

10
sub info ... 
1
sub info ... 

可以看到,在不同的變量調用count實例變量時,得到的結果不同;而在不同的變量調用info()方法時,得到的結果卻相同!

我們可以這樣理解:

當變量的編譯時類型和運行時類型不一致時,通過該變量訪問它所引用的對象的實例變量時,實例變量的值由聲明該變量(就是調用對象的那個變量)的類型決定。

當通過該變量訪問它所引用的對象的方法時,該方法的行爲由它實際所引用的對象類型決定(也就是,子類覆蓋了父類的方法)。


原因:

當程序創建了一個子類對象時,系統不僅會爲該類中定義的實例變量分配內存,也會爲其父類中聲明的所有實例變量分配內存,即使子類定義了與父類中同名的實例變量。
如果在子類裏定義了與父類中已有變量同名的變量,那麼子類中定義的變量會隱藏父類中定義的變量。但注意,不是完全隱藏。因此係統在創建子類對象時,依然會爲父類中的被隱藏的變量分配內存空間。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章