一、泛型出現的背景
早期Java是使用Object來代表任意類型的,這樣使用會出現兩個問題:
- Collection、Map集合對元素的類型無法做限制。本來我的Collection集合想裝載的只能是Dog對象,但是外邊把Cat對象存儲到集合中,是沒有任何語法錯誤的。
- 把對象扔進集合中,集合是不知道元素的類型是什麼的,僅僅知道是Object。因此在get()的時候,返回的是Object,還需要強制轉換。
爲了解決這兩個問題,泛型應運而生,我們通過泛型可以限制某個類(常應用在集合類中)中元素的類型,並且get時不需要進行強轉。
二、自定義一個簡單的泛型類
public class GenericTest<T> {
private T genericValue;
public T getGenericValue() {
return genericValue;
}
public void setGenericValue(T genericValue) {
this.genericValue = genericValue;
}
public static void main(String[] args) {
GenericTest<String> stringGenericTest = new GenericTest<>();
// 1、只能set String類型的值
stringGenericTest.setGenericValue("123");
// 2、存放整形的值會報錯
// stringGenericTest.setGenericValue(123);
// 3、取出的值不需要強轉
String stringValue = stringGenericTest.getGenericValue();
System.out.println(stringValue);
// 4、且必須用String來接收,不然會報錯
// Integer integer = stringGenericTest.getGenericValue();
}
}
三、注意事項
- 什麼是類型擦除?
Java中的泛型是在編譯器這個層次來實現的,生成的Java字節碼中是不包含泛型的類型信息的。而泛型的類型參數,會在編譯器在編譯的時候去掉,這個過程就稱爲類型擦除。
如:
第五條:在代碼中定義的ArrayList和ArrayList類型,在編譯後都會變成List。
第六條:通過反射可以在Integer集合中的Integer類型被擦除後存放字符串
// 5、泛型的類型擦除證明:兩個ArrayList編譯後的類型是相同的
ArrayList<String> stringArrayList = new ArrayList<>();
stringArrayList.add("123");
ArrayList<Integer> integerArrayList = new ArrayList<>();
integerArrayList.add(123);
System.out.println(stringArrayList.getClass() == integerArrayList.getClass());
// 6、類型擦除的證明:通過反射可以跳過編譯階段的類型檢測將字符串存到整形集合中
integerArrayList.getClass().getMethod("add",Object.class).invoke(integerArrayList,"我是字符串");
System.out.println(integerArrayList.get(1));
更多細節參考大神博文:泛型的類型擦除