一、擦除的原因
主要是Java从非泛化代码到泛化代码,为了向前兼容旧版本做出的妥协
二、擦除的代价
显著的代价就是运行时不能保留泛型信息,由此也就不能显式地引用运行时操作,比如转型instanceOf 操作和new 表达式。
比如:
Class Foo<T>{
T bar;
}
Foo<Dog> foo = new Foo<>();
看起来:当创建Foo的实例时,这个类是基于Dog的,但其实这个类只是基于Object的。
三、擦除后的继承
Java的泛型是基于擦除机制的,当有泛型的类涉及到类的继承时,往往会令人疑惑。
public class GenericBase<T> {
private T obj;
public T getObj() {
return obj;
}
public void setObj(T obj) {
this.obj = obj;
}
}
/**
* 父子都有泛型
* @param <T>
*/
class Derived1<T> extends GenericBase<T> {
}
/**
* 父子都无泛型
*/
class Derived2 extends GenericBase {
}
/**
* 如有<?> IDE会提示:no wildcard type expected,
* 表示编译器其实希望得到一个原生类
*/
class Derived3 extends GenericBase/*<?>*/ {
}
/**
* 子有泛型,父无泛型
*/
class Derived4<T> extends GenericBase {
}
class TestDerived {
public static void main(String[] args) {
/*1*/
Derived1<String> stringDerived1 = new Derived1<>();
String stringDerived1Obj = stringDerived1.getObj();
stringDerived1.setObj(stringDerived1Obj);
/*2 */
Derived2 derived2 = new Derived2();
Object derived2Obj = derived2.getObj();
derived2.setObj(derived2Obj); // IDE 会给出Uncheck Call 的提示
/*3*/
Derived3 derived3 = new Derived3();
Object derived3Obj = derived3.getObj();
derived3.setObj(derived3Obj);// IDE 会给出Uncheck Call 的提示
/*4*/
Derived4<String> stringDerived4 = new Derived4<>();
Object stringDerived4Obj = stringDerived4.getObj();
stringDerived4.setObj(stringDerived4Obj); // IDE 会给出Uncheck Call 的提示
}
}