多態是繼封裝、繼承之後,面向對象的第三大特性。
Java作爲面向對象的語言,同樣可以描述一個事物的多種形態。如Student類繼承了Person類,一個Student的對象便既是Student,又是Person。
Java中多態的代碼體現在一個子類對象(實現類對象)既可以給這個子類(實現類對象)引用變量賦值,又可以給這個子類(實現類對象)的父類(接口)變量賦值。
最終多態體現爲父類引用變量可以指向子類對象。
多態的前提是必須有子父類關係或者類實現接口關係,否則無法完成多態。
在使用多態後的父類引用變量調用方法時,會調用子類重寫後的方法。
1. Java中多態的定義與使用格式
多態的定義格式,就是父類的引用變量指向子類對象。父類類型 變量名 = new 子類類型(); 變量名.方法名();
①普通類多態定義的格式: 父類 變量名 = new 子類(); 如:
class Fu{}
class Zi extends Fu {}
//類的多態使用
Fu f = new Zi();
②抽象類多態定義的格式: 抽象類 變量名 = new 抽象類子類(); 如:
abstract class Fu {
public abstract void method();
}
class Zi extends Fu {
public void method(){
System.out.println("重寫父類抽象方法");
}
}
//類的多態使用
Fu fu = new Zi();
③接口多態定義的格式: 接口 變量名 = new 接口實現類(); 如:interface Fu {
public abstract void method();
}
class Zi implements Fu {
public void method(){
System.out.println(“重寫接口抽象方法”);
}
}
//接口的多態使用
Fu fu = new Zi();
注意事項:同一個父類的方法會被不同的子類重寫。在調用方法時,調用的爲各個子類重寫後的方法。
當變量名指向不同的子類對象時,由於每個子類重寫父類方法的內容不同,所以會調用不同的方法。
2.多態-成員的特點
①多態出現後會導致子父類中的成員變量有微弱的變化。
多態成員變量——當子父類中出現同名的成員變量時,多態調用該變量時:
編譯時期:參考的是引用型變量所屬的類中是否有被調用的成員變量。沒有,編譯失敗。
運行時期:也是調用引用型變量所屬的類中的成員變量。
簡單記:編譯和運行都參考等號的左邊。編譯運行看左邊。
②多態出現後會導致子父類中的成員方法有微弱的變化。
多態成員方法
編譯時期:參考引用變量所屬的類,如果沒有類中沒有調用的方法,編譯失敗。
運行時期:參考引用變量所指的對象所屬的類,並運行對象所屬類中的成員方法。
簡而言之:編譯看左邊,運行看右邊。
3.instanceof關鍵字
通過instanceof關鍵字來判斷某個對象是否屬於某種數據類型。使用格式:boolean b = 對象 instanceof 數據類型; 如:
Person p1 = new Student(); // 前提條件,學生類已經繼承了人類
boolean flag = p1 instanceof Student; //flag結果爲true
boolean flag2 = p2 instanceof Teacher; //flag結果爲false
4.多態-轉型
多態的轉型分爲向上轉型與向下轉型兩種:
①向上轉型:當有子類對象賦值給一個父類引用時,便是向上轉型,多態本身就是向上轉型的過程。
使用格式:父類類型 變量名 = new 子類類型();
當不需要面對子類類型時,通過提高擴展性,或者使用父類的功能就能完成相應的操作,這時就可以使用向上轉型。
②向下轉型:一個已經向上轉型的子類對象可以使用強制類型轉換的格式,將父類引用轉爲子類引用,這個過程是向下轉型。如果是直接創建父類對象,是無法向下轉型的!
使用格式: 子類類型 變量名 = (子類類型)父類類型的變量;
當要使用子類特有功能時,就需要使用向下轉型。
弊端是:需要面對具體的子類對象;在向下轉型時容易發生ClassCastException類型轉換異常。在轉換之前必須做類型判斷。