在嚴格的泛型代碼中,帶有泛型聲明的類總應該帶着泛型參數,但為了與老的Java代碼保持一致,也允許在使用帶泛型聲明的類時不指定實際的類型,如果沒有這個泛型指定實際類型,此時被稱作raq type(原始類型),默認時聲明該泛型形參
時指定的第一個上限類型.
package com.j1803;
class Apple<T extends Number>{
private T size;
public Apple(T size) {
this.size = size;
}
public T getSize() {
return size;
}
public void setSize(T size) {
this.size = size;
}
public Apple(){
}
}
public class ErasureTest {
public static void main(String[] args) {
Apple<Integer> ig=new Apple<>(45);
//ig的getSize()方法返回Integer類型對象
Integer as=ig.getSize();
System.out.println(as);
//ig賦值給Apple變量,丟失尖括號里的類型信息
Apple a=ig;
//a只知道size的類型是Number;
Number nm=a.getSize();
//下面代碼引起編譯錯誤a.getSize():java.lang.Number. ig1:java.lang.Integer
// Integer ig1=a.getSize();
}
}
上面程序定義了一個帶有泛型聲明的類AppLe類,其泛型形參的上限是Number,這個泛型形參用來定義Apple類的size變量.當把帶有泛型信息的對象賦值給一個不帶泛型信息的變量時,編譯器就會丟失原來對象的泛型信息,也就是尖括號
里的信息都會丟失,因為Apple的泛型形參的上限是Number類,所以編譯器依然知道a的getSize()返回的是Number類型,但具體是Number的哪個子類就不清楚了
從邏輯上來看,List<String>是List的子類,如果直接把List對象賦給一個List<String>對象應該會引起編譯錯誤,但實際不會.對泛型而言,可以直接把一個List對象賦給一個List<String>對象,僅僅提示"未經檢查的轉換",
package com.j1803;
import java.util.ArrayList;
import java.util.List;
public class ErasureTest2 {
public static void main(String[] args) {
List<Integer> list=new ArrayList<>();
list.add(1);
list.add(2);
List list1=list;
List<String> ls=list1;
//運行時提示報錯
System.out.println(ls.get(0));
}
}
java.lang.Integer cannot be cast to java.lang.String
Java允許直接把List對象賦給一個List<Type>(Type可以是任何類型)類型的變量,所以程序編譯通過,但對於list變量實際上引用的是List<Integer>集合,所以當試圖把該集合里的元素當成String類型的對象取出時,將引發
ClassCastException異常.