------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();
A. 靜態隨着類的加載而加載
B. 靜態代碼塊 -- 構造代碼塊 –構造方法
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("玩遊戲");
}
}