1. 程式人生 > >03 Java難點攻克-泛型

03 Java難點攻克-泛型

泛型

一,泛型概念:

泛型,“泛”為廣泛之意,“型”為型別之意。就是廣泛適用的型別。
其中準確的說法是:引數化型別,如同實參傳參給形參的方式,將型別當成一個引數進行傳遞。

二,泛型分類

1,泛型類
2,泛型方法
3,泛型介面

使用方式:

二,泛型類

定義泛型類:

許可權修飾符 class 類名<型別引數>{
	T test;	//全域性變數
}
public class Test<T>{
T mytest;
}

public static void main(String[] args){
Test<String>
test1 = new Test<>(); Test<Integer> test2 = new Test<>(); }

注意:
“T”指的是型別引數,它可以為任意字母或者字串,但建議使用公認統一的方式定義型別引數,如下:

  1. T 代表一般的任何類。
  2. E 代表 Element 的意思,或者 Exception 異常的意思。
  3. K 代表 Key 的意思。
  4. V 代表 Value 的意思,通常與 K 一起配合使用。
  5. S 代表 Subtype 的意思,文章後面部分會講解示意。

三,泛型方法

定義泛型方法:

許可權修飾符 <引數化型別> 返回值 方法名(引數化型別 形參){
	方法體;
}

示例:

public class Test(){
	publib  <T> void DemoTest(T t){
		方法體;
	}
}

注意:
其一:泛型類和泛型方法中的“”被稱為型別引數,泛型方法中的的“(T)”被稱為引數化型別,
其二:泛型方法中宣告的型別引數可以作為方法的返回值型別。
其三:泛型類與泛型方法共存問題,當兩者共存時,泛型類中的型別引數與泛型方法中的型別引數沒有聯絡,泛型方法始終以自己定義的泛型引數為準。

示例一:

pulic <T> T demoTest(T t){
		方法體;
}

例項二:

public class
Test<T>{ /** *方法demoTest02的<T>與類Test的<T>沒有聯 */ public void demoTest01(T t){ return null; } public <T> T demoTest02(T t){ return null; } }

四,泛型介面(與泛型類類似,不多加贅述)

定義泛型介面:

修飾符 Interface 介面名 <型別引數>{
	介面體;
}

示例:

public Interface DemoInterface<T>{
	介面體;
}


泛型萬用字元

一,泛型萬用字元

萬用字元概念:
子類與父類具有繼承關係,為了處理子父類範圍內的資料型別,因此就有萬用字元,萬用字元的出現是為了指定泛型中的類型範圍。

二,萬用字元分類

1,<?>無限定萬用字元
2,<? extends T>上限萬用字元
3,<? super T>下限萬用字元

三,使用方式

一,無限定萬用字元

public void domeTest(Collection<?> collectio{
//只能呼叫 Collection 中與型別無關的方法,
	 只有讀的功能 。
}

二,上限萬用字元

public void domeTest(Collection<? extends A> collection{
//表示Collection接受A類以及A的子類的型別,只有讀的功能。
}

三,下限萬用字元

public void domeTest(Collection<? super B> collection){
//表示Collection接受B類以及B的超類,具有寫的功能。
}

泛型擦除

泛型擦除概念

泛型資訊只存在於程式碼編譯階段,在進入 JVM 之前,與泛型相關的資訊會被擦除掉,專業術語叫做型別擦除

金典例題:

List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());
//結果: 返回true。

分析:因為List和List在JVM中的Class都是List.class。泛型資訊被擦除了。
結論:在泛型類被型別擦除的時候,之前泛型類中的型別參 數部分如果沒有指定上限,如 則會被轉譯成普通的 Object型別,如果指定了上限如 則型別引數就被替換成型別上限。