public class GenericType {
public static void main(String[] args) {
ArrayList<String> arrayString=new ArrayList<String>();
ArrayList<Integer> arrayInteger=new ArrayList<Integer>();
System.out.println(arrayString.getClass()==arrayInteger.getClass());
}
}
輸出:
true
在這個(gè)例子中,我們定義了兩個(gè)ArrayList數(shù)組紫谷,不過一個(gè)是ArrayList<String>泛型類型,只能存儲(chǔ)字符串。一個(gè)是ArrayList<Integer>泛型類型笤昨,只能存儲(chǔ)整型祖驱。最后,我們通過arrayString對(duì)象和arrayInteger對(duì)象的getClass方法獲取它們的類信息并比較瞒窒,發(fā)現(xiàn)結(jié)果為true捺僻。
這是為什么呢,明明我們定義了兩種不同的類型崇裁?因?yàn)樨芭鳎诰幾g期間,所有的泛型信息都會(huì)被擦除寇壳,List<Integer>和List<String>類型醒颖,在編譯后都會(huì)變成List類型(原始類型)妻怎。Java中的泛型基本上都是在編譯器這個(gè)層次來實(shí)現(xiàn)的壳炎,這也是Java的泛型被稱為“偽泛型”的原因。
public class ReflectInGeneric {
public static void main(String[] args) throws IllegalArgumentException,
SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
ArrayList<Integer> array=new ArrayList<Integer>();
array.add(1);//這樣調(diào)用add方法只能存儲(chǔ)整形逼侦,因?yàn)榉盒皖愋偷膶?shí)例為Integer
array.getClass().getMethod("add", Object.class).invoke(array, "asd");
for (int i=0;i<array.size();i++) {
System.out.println(array.get(i));
}
}
}
輸出:
1
asd
為什么呢匿辩?我們?cè)诮榻B泛型時(shí)指出向ArrayList<Integer>中插入String類型的對(duì)象,編譯時(shí)會(huì)報(bào)錯(cuò)¢欢現(xiàn)在為什么又可以了呢铲球?
我們?cè)诔绦蛑卸x了一個(gè)ArrayList<Integer>泛型類型,如果直接調(diào)用add方法晰赞,那么只能存儲(chǔ)整形的數(shù)據(jù)稼病。不過當(dāng)我們利用反射調(diào)用add方法的時(shí)候,卻可以存儲(chǔ)字符串掖鱼。這說明ArrayList<Integer>泛型信息在編譯之后被擦除了然走,只保留了原始類型,類型變量(T)被替換為Object戏挡,在運(yùn)行時(shí)芍瑞,我們可以行其中插入任意類型的對(duì)象。
但是褐墅,并不推薦以這種方式操作泛型類型拆檬,因?yàn)檫@違背了泛型的初衷(減少強(qiáng)制類型轉(zhuǎn)換以及確保類型安全)。當(dāng)我們從集合中獲取元素時(shí)妥凳,默認(rèn)會(huì)將對(duì)象強(qiáng)制轉(zhuǎn)換成泛型參數(shù)指定的類型(這里是Integer)竟贯,如果放入了非法的對(duì)象這個(gè)強(qiáng)制轉(zhuǎn)換過程就會(huì)出現(xiàn)異常。