泛型 - 类层次

跟非泛型类一样,泛型类也可以作为父类或子类,从而成为类层次的一部分。其中的关键区别是:在泛型类层次中,所有子类都必须向上传递父类所需要的所有类型参数。

泛型父类

例子

public class Generic<T> {

    private T obj;

    public Generic(T obj) {
        this.obj = obj;
    }

    public T getObj() {
        return obj;
    }

    public void setObj(T obj) {
        this.obj = obj;
    }

}

public class SubGeneric<T> extends Generic<T> {

    public SubGeneric(T obj) {
        super(obj);
    }

}

注意

  • 除了将T传递给父类外,SubGeneric没有再使用类型参数T。因此即使子类不需要泛型化,也仍然必须指定泛型父类所需要的类型参数。
  • 除了传递给父类的类型参数外,子类还可以添加自己的类型参数。
public class SubGeneric<T, V> extends Generic<T> {

    private V obj2;
    
    // ...
    
}

泛型子类

非泛型类可以作为泛型子类的父类。

public class Generic<T> extends NonGeneric {

    private T obj;
    
    // ...
    
}

运行时类型比较

instanceof运算符用于在运行时判定对象是否是某个类的实例。如果对象是指定类型的实例或者可以转换成指定的类型,就返回true。

Generic<Integer> iInstanceOne = new Generic<Integer>(10);
SubGeneric<Integer> iInstanceTwo = new SubGeneric<Integer>(20);
SubGeneric<String> sInstance = new SubGeneric<String>("test");

iInstanceOne instanceof Generic<?> // true
iInstanceOne instanceof SubGeneric<?> // false

iInstanceTwo instanceof Generic<?> // true
iInstanceTwo instanceof SubGeneric<?> // true

sInstance instanceof Generic<?> // true
sInstance instanceof SubGeneric<?> // true

注意:因为在编译的时候泛型类型信息就会被擦除,所以在运行时不能使用泛型类型信息。下面的代码无法通过编译:

iInstanceTwo instanceof SubGeneric<Integer>

强制类型转换

一个泛型类实例只能转换成另一个类型兼容且类型参数相同的泛型类实例。

(Generic<Integer>) iInstanceTwo // OK
(Generic<Long>) iInstanceTwo // error

重写泛型类的方法

可以像重写其他任何方法那样重写泛型类的方法。

public class SubGeneric<T> extends Generic<T> {

    public SubGeneric(T obj) {
        super(obj);
    }

    @Override
    public T getObj() {
        System.out.println("SubGeneric getObj()");

        return super.getObj();
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容