Java-泛型

392 阅读4分钟

泛型的简介

泛型的使用

泛型类和泛型接口

泛型的实质:

允许在定义接口、类时声明类型形参,类型形参在整个接口、类体内可当成类型使用,几乎所有可使用普通类型的地方都可以使用这种类型形参。

//定义接口时指定了一个类型形参,该形参名为E
public interface List<E> extends Collection<E> {
    //在该接口里,E可以作为类型使用
    public E get(int index) {
    }

    public void add(E e) {
    }
}

//定义类时指定了一个类型形参,该形参名为E
public class ArrayList<E> extends AbstractList<E> implements List<E> {
    //在该类里,E可以作为类型使用
    public void set(E e) {
        //TODO ...
    }
}

泛型类

public class Container<K, V> {}

泛型类派生子类

正确的方式:

public class A extends Container<Integer, String>{}

也可以不指定具体的类型,如下:

public class A extends Container{}

此时系统会把K,V形参当成Object类型处理。

泛型的方法

修饰符<T, S> 返回值类型 方法名(形参列表){
方法体
}

注意:方法声明中定义的形参只能在该方法里使用,而接口、类声明中定义的类型形参则可以在整个接口、类中使用。

泛型构造器

一种是显式指定泛型参数,另一种是隐式推断。

类型通配符

类型通配符是一个问号(?)

带限通配符

使用通配符的目的是来限制泛型的类型参数的类型,使其满足某种条件,固定为某些类。

上限通配符extends

如果想限制使用泛型类别时,只能用某个特定类型或者是其子类型才能实例化该类型时,可以在定义类型时,使用extends关键字指定这个类型必须是继承某个类,或者实现某个接口,也可以是这个类或接口本身

//它表示集合中的所有元素都是Shape类型或者其子类
List<? extends Shape>

这就是所谓的上限通配符,使用关键字extends来实现,实例化时,指定类型实参只能是extends后类型的子类或其本身

//Circle是Shape子类
List<? extends Shape> list = new ArrayList<Circle>();

这样就确定集合中元素的类型,虽然不确定具体的类型,但最起码知道其父类。然后进行其他操作。

下限通配符super

如果想限制使用泛型类别时,只能用某个特定类型或者是其父类型才能实例化该类型时,可以在定义类型时,使用super关键字指定这个类型必须是是某个类的父类,或者是某个接口的父接口,也可以是这个类或接口本身

//它表示集合中的所有元素都是Circle类型或者其父类
List <? super Circle>

这就是所谓的下限通配符,使用关键字super来实现,实例化时,指定类型实参只能是extends后类型的子类或其本身

//Shape是其父类
List<? super Circle> list = new ArrayList<Shape>();

RxJava中的应用

RxJava是最经典的泛型应用了吧

这个map的处理实在是精髓所在

    @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final <R> Observable<R> map(Function<? super T, ? extends R> mapper) {
        ObjectHelper.requireNonNull(mapper, "mapper is null");
        return RxJavaPlugins.onAssembly(new ObservableMap<T, R>(this, mapper));
    }

上限下限模式---读写模式

什么时候是上限下限模式?

方法中以泛型参数的形式存在时候

什么时候是读写模式?

真正使用到泛型的时候

        Observable2.create(new ObservableOnSubscribe2<Integer>() {
            @Override
            public void subscribe(Observer2<? super Integer> emitter) {
                emitter.onNext(10);
                emitter.onComplete();
            }
        }).

其中 subscribe(Observer2<? super Integer> emitter)中的emitter 用到了,

所以这里要调用emitter.onNext(10);的话就要用到super.


? super T--> 下限:T or T

所有父类,都可以,所以属于把下面的类型给限制了,下面的类型不能低于T,不能是T的子类,否则编译不通过.

? super T--> 可写不完全可读
? extends R --> 上限:R or R

所有子类,都可以,所以属于把上面的类型给限制了,上面的类型不能高于R,不能是R的父类,否则编译不通过.

? extends R --> 可读不可写

类型擦除