Java 泛型擦除的问题(三)

一、擦除的原因

主要是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 的提示
    }
}

猜你喜欢

转载自blog.csdn.net/qq_30118563/article/details/82119796