泛型擦除
Java 泛型的參數只可以代表類,不能代表個別對象。由於 Java 泛型的類型參數之實際類型在編譯時會被消除,所以無法在運行時得知其類型參數的類型。Java 編譯器在編譯泛型時會自動加入類型轉換的編碼,故運行速度不會因為使用泛型而加快。-----百度百科
泛型擦除的體現
通過以下代碼來感受以下什么是泛型擦除:
public class Erase {
public static void main(String[] args) {
// 創建兩個不同泛型的list集合
List<Integer> integerList = new ArrayList<>();
List<String> stringList = new ArrayList<>();
System.out.println(integerList.getClass() == stringList.getClass());
System.out.println("integerList----> "+integerList.getClass().getName());
System.out.println("stringList----> "+stringList.getClass().getName());
}
}
輸出結果
true
integerList----> java.util.ArrayList
stringList----> java.util.ArrayList
很明顯發現,兩個集合的泛型不同,但是比較class,返回的是true,並且通過反射獲取到的className是java.util.ArrayList
不管是 ArrayList<Integer> 還是 ArrayList<String>,在編譯完成后都會被編譯器擦除成了 ArrayList。
Java 泛型擦除是 Java 泛型中的一個重要特性,其目的是避免過多的創建類而造成的運行時的過度消耗。所以,想 ArrayList<Integer> 和 ArrayList<String> 這兩個實例,其實類實例是同一個。
可以把其他類型的數據放到指定了泛型的list集合中嗎?
當然是可以的。因為泛型擦除的原因。完全可以將不相干的類型的數據存入指定泛型的集合中。
如下所示添加,肯定是要報錯的,因為在編譯的時候設定了規則,編譯是不可能通過的。
按理說,因為泛型擦除的原因,完全是可以將不相干類型的數據放到指定泛型的集合中的。其實,可以換一種思路,當list集合運行起來之后,這個list集合因為泛型擦除是沒有指定泛型的,即class是沒有泛型的,所以可以在運行期間獲取這個list集合,然后將值放到該list集合中。
public class Erase {
public static void main(String[] args) {
Erase erase = new Erase();
erase.testErase();
}
List<Integer> integerList = new ArrayList<>();
List<String> stringList = new ArrayList<>();
public void testErase(){
Double d = 10d;
try {
// 通過反射機制獲取字段,然后將double類型的數據放入泛型為Integer集合中
Field integerField = this.getClass().getDeclaredField("integerList");
integerField.setAccessible(true);
List integerFieldList = (List) integerField.get(this);
integerFieldList.add(d);
// 通過反射機制獲取字段,然后將double類型的數據放入泛型為String集合中
Field stringField = this.getClass().getDeclaredField("stringList");
stringField.setAccessible(true);
List stringFieldList = (List) stringField.get(this);
stringFieldList.add(d);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("integerList ---> "+integerList);
System.out.println("stringList ---> "+stringList);
}
}
輸出結果
integerList ---> [10.0]
stringList ---> [10.0]