黑馬程序員--Java基礎學習筆記【繼承、多態】

 

 ------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! -------    

 

  • 繼承 class 子類名extends 父類名{}

繼承的好處:提高代碼複用性;提高代碼維護性;類之間產生關係,多態的前提。

繼承的特點:只支持單繼承;支持多層繼承

子類可以使用父類所有的非私有成員

子類不能繼承父類的構造方法,但是可以通過 super 訪問

 

  • super 關鍵字父類存儲空間的標識

在子類中,訪問父類的成員, super.父類成員,不能寫在靜態裏面

 

  • 繼承中構造方法的關係

子類中所有的構造方法都默認會訪問父類中空參數的構造方法

子類構造方法的第一行,有一條默認的隱式代碼 super(); 調用父類空參數的構造方法

考慮到父類中成員變量的賦值情況,父類構造器沒有對成員變量進行賦值,父類中重載的構造方法可以在子類中對 super() 傳參數調用,即子類初始化之前要先完成父類初始化

 

*父類中沒有默認的空參構造方法,子類構造方法中必須手動寫 super() 指定參數列表

構造方法第一行,this() 和 super() 只能寫一個

 

  • this 和 super 用法的區別

this 指本類對象的引用,super 父類存儲空間標識

訪問成員變量:

    this.成員變量   super.成員變量

訪問構造方法

    this(); 用於本類構造方法之間互相調用

    super(); 子類的構造方法默認訪問父類中空參的構造方法

訪問成員方法

    this.成員方法   super.成員方法

 

  • 子父類中靜態代碼塊、構造代碼塊、構造方法的執行順序

class Fu {

    static {

        System.out.println("靜態代碼塊Fu");

    }

    {

        System.out.println("構造代碼塊Fu");

    }

    public Fu() {

        System.out.println("構造方法Fu");

    }

}

 

class Zi extends Fu {

    static {

        System.out.println("靜態代碼塊Zi");

    }

    {

        System.out.println("構造代碼塊Zi");

    }

    public Zi() {

        System.out.println("構造方法Zi");

    }

}

 

Zi z = new Zi();

  1. A.  靜態隨着類的加載而加載

  2. B.  靜態代碼塊 -- 構造代碼塊 –構造方法

  3. C.  只要有繼承關係,先初始化父類的數據,再初始化子類數據

結果:

靜態代碼塊Fu

靜態代碼塊Zi

構造代碼塊Fu

構造方法Fu

構造代碼塊Zi

構造方法Zi


  • 繼承中成員方法的關係

子類重寫父類的方法,權限必須大於等於父類方法的權限,剩餘方法聲明部分須和子類一致

靜態方法嚴格意義上沒有重寫,如果靜態方法被覆蓋,則子類中的方法也是靜態的

 

  • final 關鍵字

修飾類,類成爲最終類,不能被繼承,沒有子類

修飾成員方法,方法成爲最終方法,不能被子類重寫,可以調用

修飾成員變量,成員變量在堆內存中有默認值

    final 固定的是成員變量的手動賦值,而不是默認值

 

構造方法可以對成員變量初始化賦值,但是普通方法不可以對 final 成員變量賦值

因爲構造方法是運行在對象建立過程中,普通方法調用時,對象已經建立完成了

 

  • 多態性

多態前提和體現:繼承、方法重寫,父類引用指向子類對象(反之不行)

多態的好處:程序的擴展性提高,父類固定不變子類是可以無限擴展的;維護性提高

多態的弊端:不能訪問子類的特有功能

多態的意義:一個類型的引用在指向不同的對象時會有不同的實現;

同樣一個對象,造型成不同的類型時,會有不同的功能。

 

  • 多態調用中編譯和運行時期的特性:

    非靜態成員變量、靜態成員變量:

        編譯時期,看父類中有沒有這個變量,有編譯成功,沒有編譯失敗

        運行時期,運行的是父類中的成員變量

    非靜態成員方法:

        編譯時期,看父類中有沒有這個方法,有編譯成功,沒有編譯失敗

        運行時期,運行的是子類重寫後的方法

    靜態成員方法:

        編譯時期,看父類中有沒有這個方法,有編譯成功,沒有編譯失敗

        運行時期,運行的是父類中的方法(所以說靜態方法不能算方法的重寫)

總結:除非靜態的方法以外,編譯和運行都看父類;

只有非靜態的方法,編譯看父類,運行看子類。

多態調用中,方法必走子類重寫

編譯看左邊,運行看右邊

Fu f     =     newZi();

 

  • 多態中的轉型問題(孔子裝爹案例)

向上轉型:父類類型的引用指向子類對象;接口引用指向其實現類的對象

    Java編譯器根據類型檢查調用方法是否匹配

向下轉型(強制轉型):

可以通過強制類型轉換將父類型變量轉換爲子類型變量,前提是該變量指向的對象確實是該子類類型。

也可以通過強制類型轉換將變量轉換爲某種接口類型,前提是該變量指向的對象確實實現了該接口。

如果在強制轉換過程中出現違背上述兩個前提,將會拋出ClassCastException

instanceof 關鍵字

    爲避免在強轉中出現 ClassCastException 異常,可以通過 instanceof 關鍵字判斷某個引用指向的對象是否爲指定類型。

 

/*

 * 孔子裝爹案例--多態中的轉型問題

 */

publicclassKongZiDemo {

 

    publicstaticvoid main(String[] args) {

       // 多態調用:父類引用 = 子類對象

       // 子類提升爲父類的類型,自動轉換,向上轉型

       KongZiDiekd = newKongZi();

       kd.teach();

       System.out.println(kd.age);

       System.out.println("-------");

 

       // 多態:不能使用子類特有功能

       // 使用子類特有,強制類型轉換,已經提升爲父類類型的子類對象,轉回子類類型

       KongZik = (KongZi) kd; // 類型的向下轉型

       k.playGame();

       System.out.println(k.age);

    }

}

 

class KongZiDie {

    intage = 70;

 

    publicvoid teach() {

       System.out.println("講做官");

    }

}

 

class KongZi extends KongZiDie {

    intage = 40;

 

    publicvoid teach() {

       System.out.println("講論語");

    }

 

    publicvoid playGame() {

       System.out.println("玩遊戲");

    }

}


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