首先,強調一個觀點:java
對於我這樣的初學者,必定要站在虛擬機和編譯器的角度來分析java 語言的種種特性,泛型也不例外。(我認爲這個一條正確的學習經驗)程序員
寫這篇文章起源於最近在學java,有一天在路上和一個同事在討論什麼是java泛型的時候,發現有些概念很是模糊。因而,我想澄清一下,並記錄下來。學習
但願看過的朋友可以糾正裏面的錯誤。很是感謝。spa
1 關於Java 泛型機制對象
在java 最第一版本,繼承
Java 泛型是經過 繼承實現的,我認爲 這裏的繼承,不是類的繼承而是類型的繼承.開發
exampleget
public class Test編譯器
{虛擬機
Object var;
Object getVar();
Void setVar( Object );
}
這是一個類.
泛型應用是這樣作的
Test testObj= new =Test();
class A
{}
A a = new A();
a = (A)getVar();
由於A類 是Object類的子類,這樣的話,經過類型強制轉換,就能夠實現賦值。
class B ,class C等等 道理同樣。
經過這種方式實現和C++ 泛型同樣的效果。惟一須要注意的地方在於類型轉換,類型判斷這些類型相關的操做須要程序員干預。
我猜想,Java 的泛型機制就是創建在類型繼承這個基礎上,後面版本的泛型 本質上也是這樣作的
2 關於泛型的類型擦除
做爲一個泛型類的開發人員,咱們定義了一個泛型類,
好比
example
public class Test<T>
{
T var;
T getVar();
Void setVar( T t);
}
說明,這個的T 是一個相對於class Test 的類型參數,(能夠類比: 在 void func( int x ) 中,int x是相對於method : func 的類型參數,x 是類型變量同樣,)
這個泛型類在編譯器中會被作一些處理而生成一個類文件。
選擇原始類型(好比Object類),替代 類定義內的全部 T ,
將<T> 抹去
結果是生成的類文件效果等同於
public class Test
{
Object var;
Object getVar();
void setVar( Object t);
}
這個過程就叫作java 泛型類型擦除。
這個過程說明什麼呢?
說明對於編譯器而言,是不存在什麼Test<String>類,Test<Date>類等等的。
對於Test<xx> 各類對象,它們都屬於同一個類 Test ;
但要注意,編譯器看到泛型格式<T >,編譯會作一些額外的事情,好比類型轉換,橋方法等等。編譯器在這裏把之前程序員須要手動作的事情給作。
畢竟程序員寫的代碼是要給編譯器看懂的。經過泛型一些約定的規則,讓程序員的意圖爲編譯器所準確知道,這樣寫出的代碼纔不會有問題。
3泛型類型的繼承問題
首先,繼承是一個類,類型之間關係的問題,因此就和對象沒有關係.對象之間不存在繼承的問題。
在上面的分析中,咱們知道編譯器不會產生具體類型參數的類。只會生成一個原始類型的普通類。即只有一個類。
那麼這裏又何來 泛型類型的繼承問題呢?
個人理解是: 類型的繼承和類的繼承不是同一個概念,應該說,類型繼承是類型繼承,類繼承也是類型繼承,但類型繼承就不必定是類繼承
Texample : Test<String > 是 Test 的一個子類型, 並非: Test<String > 是一個類,Test 是另外一個類,Test<String > 是 Test 的子類.
在繼承這個概念中,類型繼承是一個超類,而類繼承是一個子類。,類繼承也是類型繼承的一種狀況,而不能說由於A類型是繼承B類型,就推導出A是一個類,B是另外一個類。A是B的子類。
我不知道UML裏面是否是這樣定義的。