多態java
java引用變量有兩個類型:一個是編譯時類型,一個是運行時類型。編譯時類型由聲明該變量時使用的類型決定,運行時類型由實際賦給該變量的對象決定。若是編譯時類型與運行時類型不一致,就可能出現多態(Polymorphism)。編碼
下面是一個範例:code
class BaseClass { public int book = 6; public void base() { System.out.println("父類的普通方法"); } public void test() { System.out.println("父類被覆蓋的方法"); } } public class SubClass extends BaseClass { //從新定義一個book實例Field隱藏父類的book實例Field public String book= "輕量級javaee企業應用實戰"; public void test() { System.out.println("子類的覆蓋父類的方法"); } public void sub() { System.out.println("子類的普通方法"); } public static void main(String[]args) { //下面編譯時類型和運行時類型徹底同樣,所以不存在多態 BaseClass bc = new BaseClass(); //輸出6 System.out.println(bc.book); //下面兩次調用將執行BaseClass的方法 bc.base(); bc.test(); SubClass sc = new SubClass(); //輸出"輕量級j2ee企業應用實戰" System.out.println(sc.book); sc.base(); sc.test(); BaseClass ploymophicBc = new SubClass(); System.out.println(ploymophicBc.book); //下面調用將執行從父類繼承到的base方法 ploymophicBc.test(); //由於ploymophicBc 的編譯時類型是BaseClass //BaseClass 類沒有提供sub方法,因此下面代碼編譯出錯 //ploymophicBc.sub(); } }
上面程序的main方法中顯式建立了三個引用變量,對於前兩個引用變量bc和sc,他們編譯時和運行時類型徹底相同,所以調用它們的Field和方法很是正常。第三個引用變量ploymophicBc則比較特殊,它編譯時類型是BaseClass,而運行時類型是SubClass,當調用該引用變量的test方法時,實際執行的是SubClass類中覆蓋後的test方法,因而出現多態。對象
由於子類實際上是一種特殊的父類,所以java容許把一個子類對象直接賦給一個父類引用變量,無須任何類型轉換,或者被稱爲向上轉型(upcasting),向上轉型由系統自動完成。繼承
當把一個子類對象直接賦給父類引用變量時,其方法行爲老是表現出子類方法的行爲特徵,而不是父類行爲特徵,這就會出現:相同類型的變量,調用同一個方法時呈現出多種不一樣的行爲特徵,這就是多態。對象的Field不具有多態性。io
引用變量在編譯階段只能調用其編譯時類型所具備的方法,但運行時則執行它運行時類型所具備的方法。所以,編寫java編碼時,引用變量只能調用聲明該變量時所用類裏包含的方法。編譯
經過引用變量來訪問其它包含的實例Field時,系統老是識圖訪問它編譯時類型所定義的Field,而不是它運行時類型所定義的Field。ast
引用類型的強制類型轉換class
類型轉換運算符是小括號,類型轉換運算符的用法是:(type)variable,這種用法能夠將bariable變量轉換成一個type類型的變量。當進行強制類型轉換時須要注意:test
》基本類型之間的轉換隻能在數值類型之間進行,包括整數型,字符型和浮點型。
》引用類型之間的轉換隻能在具備繼承關係的兩個類型之間進行,若是試圖把一個父類實例轉換成子類類型,則沒法節能型類型轉換,負責編譯出錯,若是試圖把一個父類實例轉換成子類類型,則把這個對象必須其實是子類實例才行(即編譯時類型爲父類類型,而運行時類型是子類類型),不然將在運行時出現ClassCastException異常。用instanceof運算符來判斷是否能夠成功轉換。