【javase複習】## day 4 繼承的內存分析、super、final ##

繼承

繼承的主要目的是 描述兩個類的關係 和 減少重複代碼

注意細節:
①父類的私有成員不能被繼承
②父類的構造函數不能被繼承
③創建子類對象的時候java編譯器會默認加上super()去先調用父類的無參的構造方法以賦值一些變量。

我們知道一個類如果自定義了構造方法,就不會被編譯器默認加上無參構造方法,那麼這個時候去繼承要注意:
① 在Fu類中聲明一個無參的構造方法
② 在Zi類中明確調用父類帶參的構造方法。




子類和父類在內存中是怎麼樣存在的呢。
首先引入super關鍵字
指代 堆內存中, 子類對象中 ,父類空間的空間引用。
與this不同,他並不是函數調用者的一個對象,而是一片內存空間的入口,雖然這片內存空間與一個真實的父類對象的內存空間一樣
我們用一段代碼解釋:

class Person{

    String name;

    private int age;

    public  Person(String name){
        this.name = name;
    }

    public Person(){
        System.out.println("Person類的構造方法被調用了....");
    }

    public void eat(){
        System.out.println(name+"在吃飯...");
    }
}

//學生類
class Student extends Person {  // Student 就稱作爲Person類的子類, Person類就稱作爲Student的父類(超類、基類)

    int num; //學號

    public Student(){
        System.out.println("Student類的構造方法被調用了....");
    }

    public void study(){
        System.out.println(name+"good good study , day day up");
    }   
}




class Demo7 
{
    public static void main(String[] args) 
    {
        Student s = new Student();

        /*
        s.name = "狗娃";
        System.out.println("名字:"+ s.name);
        s.eat();
        */
    }
}

jvm在創建Student對象的時候,由於繼承,會調用多次構造函數像包裹一樣完成這個Student子類對象的創建

①java編譯器在Student的構造函數第一句添加super(),然後執行super(),即父類的無參構造函數
②於是開始調用Person的無參構造函數,並初始化一片空間存有Person類的成員變量和方法並賦值。(其實是調用super(),運行Object的構造方法。)
③一個僞Person類對象創建完成,他並不是一個對象,但是在內存中和對象一樣,並且有一個super關鍵字指向這片空間,然後再添加Student類新增的,重寫的方法形成一個Student類對象
④棧內存中的引用類型變量s 指向Student對象。堆和棧建立連接。

盜了一張圖表示這個關係。
這裏寫圖片描述



接下來要注意的是由於java的就近原則,
①如果直接是子類對象去調用成員變量或者方法,就是調用子類獨有空間中的變量或者方法
②如果子類獨有空間中沒有,就去super所指空間中尋找
③如果再沒有,再去super的super空間中所尋找

這裏寫圖片描述
在這裏我思考一個點:
如果有一個父類繼承一個祖父類,並重寫一個方法,又有一個子類繼承了父類,重寫了同一個方法,能否使用super.super.function()去在子類對象調用祖父類的方法?

答案是行不通的,這也應徵了super其實是指代一片內存空間而不是一個父類對象

另外,主要子類重寫了方法之後,對於別的類來說,相當於父類的方法不存在了,只能通過子類的類體中用super關鍵字去調用。 然後優化成方法,再從別的類中調用這個優化的方法




super關鍵字:

super關鍵字代表了父類空間的引用。

super關鍵字的 作用:
1. 子父類存在着同名的成員時,在子類中默認是訪問子類的成員,可以通過super關鍵字指定訪問父類的成員。
2. 創建子類對象時,默認會先調用父類無參的構造方法,可以通過super關鍵字指定調用父類的構造方法。


super關鍵字調用父類構造方法要注意的事項:
1. 如果在子類的構造方法上沒有指定調用父類的構造方法,那麼java編譯器會在子類的構造方法上面加上super()語句。
2. super關鍵字調用父類的構造函數時,該語句必須要是子類構造函數中的第一個語句。
3. super與this關鍵字不能同時出現在同一個構造函數中調用其他的構造函數。因爲兩個語句都需要第一個語句。

繼承的另外一個作用就是重寫

方法重寫要注意的事項:
1.方法重寫時, 方法名與形參列表必須一致。
2.方法重寫時,子類的權限修飾符必須要大於或者等於父類的權限修飾符。
3.方法重寫時,子類的返回值類型必須要小於或者 等於父類的返回值類型。
4.方法重寫時, 子類拋出的異常類型要小於或者等於父類拋出的異常類型。

方法的重載:在一個類中 存在兩個或者兩個 以上的同名函數,稱作爲方法重載。

方法重載的要求
1. 函數名要一致。
2. 形參列表不一致(形參的個數或形參 的類型不一致)
3. 與返回值類型無關。





final

final關鍵字的用法:
1. final關鍵字修飾一個基本類型的變量時,該變量不能重新賦值,第一次的值爲最終的。
2. fianl關鍵字修飾一個引用類型變量時,該變量不能重新指向新的對象。
3. final關鍵字修飾一個函數的時候,該函數不能被重寫。
4. final關鍵字修飾一個類的時候,該類不能被繼承。

常量 的修飾符一般爲: public static final

final修飾的變量不可變,成爲有名常量。
存入方法區的常量池中。但是和static變量不同,並不止維護一份且隨類文件加載而加載,而是隨着對象創建才加載,且每個對象維護一份

一般與static聯合修飾, 減少內存開銷, 不用創建對象也可使用final常量。

但是在某些特殊情況下,我們只能用final而不能用static修飾,例如一個Employee類,裏面有一個name域,表示僱員姓名,僱員姓名一旦在構造函數中被設置,以後就不能更改,所以name應該聲明爲final。但是name是屬於每個僱員的(也就是Employee類的每個實例對象),而不是屬於整個Employee類的,所以這時候,就不可聲明爲static。

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