1.為什么需要泛型
泛型在Java中有很重要的地位,網(wǎng)上很多文章羅列各種理論,不便于理解,本篇將立足于代碼介紹、總結(jié)了關(guān)于泛型的知識(shí)。希望能給你帶來(lái)一些幫助。
先看下面的代碼:
List list = new ArrayList();
list.add("CSDN_SEU_Cavin");
list.add(100);
for (int i = 0; i < list.size(); i++) {
String name = (String) list.get(i); //取出Integer時(shí),運(yùn)行時(shí)出現(xiàn)異常
System.out.println("name:" + name);
}
本例向list類型集合中加入了一個(gè)字符串類型的值和一個(gè)Integer類型的值。(這樣合法,因?yàn)榇藭r(shí)list默認(rèn)的類型為Object類型)。在之后的循環(huán)中,由于忘記了之前在list中也加入了Integer類型的值或其他原因,運(yùn)行時(shí)會(huì)出現(xiàn)java.lang.ClassCastException異常。為了解決這個(gè)問(wèn)題,泛型應(yīng)運(yùn)而生。
2.泛型的使用
Java泛型編程是JDK1.5版本后引入的。泛型讓編程人員能夠使用類型抽象,通常用于集合里面。
只要在上例中將第1行代碼改成如下形式,那么就會(huì)在編譯list.add(100)時(shí)報(bào)錯(cuò)。
List<String> list = new ArrayList<String>();
通過(guò)List<String>,直接限定了list集合中只能含有String類型的元素,從而在上例中的第6行中,無(wú)須進(jìn)行強(qiáng)制類型轉(zhuǎn)換,因?yàn)榧夏軌蛴涀∑渲性氐念愋托畔?,編譯器已經(jīng)能夠確認(rèn)它是String類型了。
3.泛型只在編譯階段有效
看下面的代碼:
AyyayList<String> a = new ArrayList<String>();
ArrayList b = new ArrayList();
Class c1 = a.getClass();
Class c2 = b.getClass();
System.out.println(a == b); //true
上面程序的輸出結(jié)果為true。所有反射的操作都是在運(yùn)行時(shí)的,既然為true,就證明了編譯之后,程序會(huì)采取去泛型化的措施,也就是說(shuō)Java中的泛型,只在編譯階段有效。在編譯過(guò)程中,正確檢驗(yàn)泛型結(jié)果后,會(huì)將泛型的相關(guān)信息擦出,并且在對(duì)象進(jìn)入和離開(kāi)方法的邊界處添加類型檢查和類型轉(zhuǎn)換的方法。也就是說(shuō),成功編譯過(guò)后的class文件中是不包含任何泛型信息的。泛型信息不會(huì)進(jìn)入到運(yùn)行時(shí)階段。
上述結(jié)論可通過(guò)下面反射的例子來(lái)印證:
ArrayList<String> a = new ArrayList<String>();
a.add("CSDN_SEU_Cavin");
Class c = a.getClass();
try{
Method method = c.getMethod("add",Object.class);
method.invoke(a,100);
System.out.println(a);
}catch(Exception e){
e.printStackTrace();
}
因?yàn)槔@過(guò)了編譯階段也就繞過(guò)了泛型,輸出結(jié)果為:
[CSDN_SEU_Cavin, 100]
4.泛型類和泛型方法
如下,我們看一個(gè)泛型類和方法的使用例子,和未使用泛型的使用方法進(jìn)行了對(duì)比,兩者輸出結(jié)果相同,在這里貼出來(lái)方便讀者體會(huì)兩者的差異。泛型接口的例子有興趣可以去找一些資料,這里就不贅述了。
(1)使用泛型的情況
public static class FX<T> {
private T ob; // 定義泛型成員變量
public FX(T ob) {
this.ob = ob;
}
public T getOb() {
return ob;
}
public void showTyep() {
System.out.println("T的實(shí)際類型是: " + ob.getClass().getName());
}
}
public static void main(String[] args) {
FX<Integer> intOb = new FX<Integer>(100);
intOb.showTyep();
System.out.println("value= " + intOb.getOb());
System.out.println("----------------------------------");
FX<String> strOb = new FX<String>("CSDN_SEU_Calvin");
strOb.showTyep();
System.out.println("value= " + strOb.getOb());
}
(2)不使用泛型的情況
public static class FX {
private Object ob; // 定義泛型成員變量
public FX(Object ob) {
this.ob = ob;
}
public Object getOb() {
return ob;
}
public void showTyep() {
System.out.println("T的實(shí)際類型是: " + ob.getClass().getName());
}
}
public static void main(String[] args) {
FX intOb = new FX(new Integer(100));
intOb.showTyep();
System.out.println("value= " + intOb.getOb());
System.out.println("----------------------------------");
FX strOb = new FX("CSDN_SEU_Calvin");
strOb.showTyep();
System.out.println("value= " + strOb.getOb());
}
輸出結(jié)果均為:
T的實(shí)際類型是: java.lang.Integer
value= 100
T的實(shí)際類型是: java.lang.String
value= CSDN_SEU_Calvin