1.關於泛型擦除
public class ErasedType {
public static void main(String[] args) {
Class c1 = new ArrayList<Integer>().getClass();
Class c2 = new ArrayList<String>().getClass();
System.out.println(c1 == c2);
}
}
上面代碼的輸出結果爲:
class Frop {
}
class Fnorkle {
}
class Quark<Q> {
}
class Particle<POOSITION, MOMENTUM> {
}
public class ErasedType {
public static void main(String[] args) {
List<Frop> list = new ArrayList<Frop>();
Map<Frop, Fnorkle> map = new HashMap<Frop, Fnorkle>();
Quark<Fnorkle> quark = new Quark<Fnorkle>();
Particle<Long, Double> particle = new Particle<Long, Double>();
System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
System.out.println(Arrays.toString(map.getClass().getTypeParameters()));
System.out.println(Arrays.toString(quark.getClass().getTypeParameters()));
System.out.println(Arrays.toString(particle.getClass().getTypeParameters()));
}
}
以上代碼的輸出結果爲:
從以上內容可以發現,在泛型代碼的內部,無法獲得任何有關泛型參數類型的信息。
由第一個例子可以看出在運行時他們是相同的類型。
第二個例子只是看到了佔位符的標識符,沒有任何有用的信息。
2.擦除的問題
泛型不能用於顯式的引用運行時類型的操作之中,例如轉型、instanceof以及new。
class Frop<T> {
}
class Cat {
}
public class ErasedType {
public static void main(String[] args) {
Frop<Cat> frop = new Frop<Cat>();
}
}
上述代碼中,只是看起來擁有相關參數的類型信息,T被Cat所替換,但是實際上並非如此,它只是一個Object。
3.擦除的補償
class Building {
}
class House extends Building {
}
public class ErasedType<T> {
Class<T> kind;
public ErasedType(Class<T> kind) {
this.kind = kind;
}
public boolean f(Object obj){
return kind.isInstance(obj);
}
public static void main(String[] args) {
ErasedType<Building> ctt1=new ErasedType<Building>(Building.class);
System.out.println(ctt1.f(new Building()));
System.out.println(ctt1.f(new House()));
ErasedType<House> ctt2=new ErasedType<House>(House.class);
System.out.println(ctt2.f(new Building()));
System.out.println(ctt2.f(new House()));
}
}
有時可以通過引入類型標籤對擦除進行補償,這意味着,有時候需要顯式地將類型的Class對象進行傳遞。以便可以在類型表達式中使用。
4.邊界
因爲擦除移除了類型信息,但是泛型重用了extends關鍵字爲泛型參數類型上設置限制條件。