1.
class Test<T> //也可以有多個泛型類型如 class Test<T,U>...以逗號分隔{ PRivate T t; //T代表某一個類型 ... public static <U> U getSomthing() //泛型方法,可以在泛型類中,也可以在普通類中。 { ... }}調用時:new Test<String>().<String>getSomthing(); //第2個對方法的泛型具體化時要放在方法名的前面。在編譯器可以根據參數自動確定方法使用的U代表哪種類型時,方法名前的<String>可以省略
2.限定泛型的類型。 例如:public static <T extends Comparable> T min(T[] a){...} //只有實現了Comparable接口的類才可以替換T 也可以限定多個類型:<T extends Comparable & Serializable> 使用&分隔 注意:無論限定為接口還是類,一律使用extends。另外,限定的最多只能有一個類,可以有多個接口,并且,類在<>中的順序放在第一個。
3.泛型代碼和虛擬機 擦除:將具體類型替換為Object類型(沒有限定泛型類型時)或者是限定泛型類型的第一個類型,例如2中的第2個代碼,將會替換為Comparable類型。 擦除之后的類型成為原始類型。
4.使用泛型時需要考慮的限制 (1)不能用基本類型實例化類型參數。例如,不能<double>,可以<Double> (2)運行時類型都會被擦除為原始類型。所以: [1]不能使用 a instanceof Pair<String>,只能夠使用 a instanceof Pair 或者 a instanceof Pair<?>。也就是說,instanceof對于泛型類只能夠判斷a是否是任意類型的一個Pair對象。 [2]對于泛型類,getClass方法也只會返回原始類型。如:Pair<String> stringPair=...; Pair<Employee> employeePair=...; 此時,stringPair.getClass()==employeePair.getClass()會返回true,因為getClass方法返回的都是Pair.class [3]也不能進行強制類型轉換,例如 Pair<String> p = (Pair<String>) a (3)不能實例化參數化類型的數組。例如:Pair<String>[] table = new Pair<String>[10]; 注意:只是不能實例化(new Pair<String>[10]),但是可以聲明(Pair<String>[] table) (4)對于參數可變的方法,可以向方法中傳入多個泛型類型的實例(實際上會將這幾個泛型實例放在一個數組中,但是這里限制有所放松,只會給出警告),例如:
但是,會隱藏著危險:
Pair<String>[] table = ...; Object[] objarray = table; objarray[0] = new Pair<Employee>(); //將一個Pair<Employee>類型的對象插入到Pair<String>類型的數組中。能夠順利運行并且沒有異常,但是在使用table[0]時,會在別處得到一個異常。(5)不能實例化類型變量,像 new T(…), new T[…], T.class都不可以使用 (6)不能在靜態域或者靜態方法中引用類型變量。例如 private static T singleInstance;(不允許有T) (7)既不能拋出也不能捕獲泛型類對象,甚至泛型類 擴展 Throwable類都是不合法的。 例如:
public class Problem<T> extends Exception{...} //這樣不可以但是下面這樣是可以的:public static <T extends Throwable> void doWork(T t) throws T {} //合法另外,java異常處理的原則是必須為所有的已檢查異常提供一個處理器,然而可以利用<T extends Throwable>消除編譯器對已檢查異常的檢查,對于如何去做,這里不詳細描述。 (8)要想支持擦除的轉換,就需要強制限制一個類或者類型變量不能同時成為兩個接口類型的子類,而這兩個接口是同一接口的不同參數化。例如,下面代碼是非法的
5.泛型類型的繼承規則 (1)Employee是Manager的超類,然而Pair<Manager>并不是Pair<Employee>類的子類,他們之間沒有任何關系。也不能用一個Pair<Employee>變量引用一個Pair<Manager>對象。 (2)永遠可以將參數化類型轉換為一個原始類型。例如,Pair<Employee>是原始類型Pair的一個子類型。
(3)泛型類可以擴展實現其他的泛型類。例如,ArrayList<T>實現List<T>接口。這意味著,一個ArrayList<Manager>可以被轉換為一個List<Manager>
6.通配符類型(帶有子類型限定的通配符可以從泛型對象讀取,帶有超類型限定的通配符可以向泛型對象寫入) (1)通配符的子類型限定 Pair<Manager>和Pair<Employee> 都是Pair<? extends Employee>的子類型。因此,可以用Pair<? extends Employee>類型的變量引用Pair<Manager>類型的對象。例如,
(2)通配符的超類型的限定 [1]像Pair<? super Manager>通配符限制為Manager的超類型(不包括Manager)。此時Pair<Employee>和Pair<Object>都是Pair<? super Manager>的 子類。 [2]可以使用set方法,但是不可以使用get方法,也就是說與(1)相反:
(3)可以使用<T extends Comparable<? super T> >替換<T extends Comparable<T> > , 因為后一種情況有時會出問題,例如當T為GregorianCalandar時,由于GregorianCalendar并親自沒有實現compareTo方法,而是從Calendar繼承來的。所以GregorianCalendar實現的是Comparable<Calendar>,而不是Comparable<GregorianCalendar>,所以會出問題。 (4)無限定通配符Pair<?>, 使用getFirst方法只能返回給一個Object變量,setFirst方法不能被調用。(但是可以setFirst(null)) *沒看懂到底有什么用 (5)通配符的捕獲 如交換Pair對象的兩個數據成員first和second
新聞熱點
疑難解答