JAVA中的向下轉型(downcasting)及泛型與向上轉型(upcasting)及RTTI、反射機制
向上轉型(upcasting):對象可以作為它本身的類型使用也可以作為它父類(基類)對象使用,java中是單繼承的,所以是一種安全的做法。
當你初始化子類時,產生一個對象時,該對象將父類的對象作為子物件包含其中。向上轉型會丟失子類的方法。但可以將所有對象至於一個共同的容器中儲存與調用,實現了容器的複用,(collection 容器集預設將所有對象作為Object儲存的),但在具體使用是要確定對象原來的身份。
Java在運行中動態識別對象和類資訊有兩種機制:
1、RTTI(run-time type identification)運行期類別識別(強制類型轉換“()”,類型轉換是在運行期進行的),它假定我們在編譯和運行期已經知道了所有的類型。
Java是通過Class對象實現RTTI機制的
Java中為每個類建立一個Class對象(*.class),它包括了與類相關的資訊,用來建立類的常規對象,在運行期,一旦我們想產生某個類的對象,運行這個程式的JVM首先檢查這個類的Class對象是否載入,如果尚未載入,JVM會根據類名尋找.class檔案,並將其載入,之後你就可以建立這個類的任何對象了。java程式不是一開始執行,所有類就被完全載入的。Class對象僅在需要時被載入,Static語句塊是在類被載入時執行。
產生Class對象的兩種引用方式:
Class.forName(“Gun”)
類字面常量: Gun.class
RTTI的限制:類在編譯期間必須已知,在編譯期間開啟和檢查.class檔案。
2、反射機制(reflection)它允許我們在運行期獲得類的資訊。
反射機制在運行期開啟和檢查.class檔案。
向下轉型(downcasting):父類對象向下轉變為具體的子類對象,但是種不安全的操作,很難確定應該轉變為怎樣的子類。
為了實現複用容器,java中定義了一個通用類型:object,作為所有類的父類,以及java單根繼承的特性,意味著object可以儲存任何類的執行個體。在使用object作為容器時,你需要在其中置入對象引用(object reference),之後可以將它們取回使用,但同時原資料對象會被向上轉型為Object,它會丟失自己的身份。怎樣才能變回原來的對象?
其解決方案是參數化型別(parameterized type),也就是說所操作的資料類型被指定為一個參數。這種參數類型可以用在類、介面和方法的建立中,分別稱為泛型類、泛型介面、泛型方法。這是JDK 5.0引入的新特性,簡稱為泛型。
沒有泛型的情況的下,通過對類型Object的引用來實現參數的“任意化”,“任意化”帶來的缺點是要做顯式的強制類型轉換,而這種轉換是要求開發人員對實際參數類型可以預知的情況下進行的。對於強制類型轉換錯誤的情況,編譯器可能不提示錯誤,在啟動並執行時候才出現異常,這是一個安全隱患。
泛型的好處是在編譯的時候檢查型別安全,並且所有的強制轉換都是自動和隱式的,提高代碼的重用率。
泛型規則和限制
1、泛型的型別參數只能是類類型(包括自訂類),不能是簡單類型。
2、同一種泛型可以對應多個版本(因為參數類型是不確定的),不同版本的泛型類執行個體是不相容的。
3、泛型的型別參數可以有多個。
4、泛型的參數類型可以使用extends語句,例如<T extends superclass>。習慣上成為“有界類型”。
5、泛型的參數類型還可以是萬用字元類型。例如Class<?> classType = Class.forName(java.lang.String)。