JAVA----泛型通配符,泛型数组

通配符

PECS原则:Producer Extends Consumer Super 如果需要返回T,它是生产者(Producer),要使用extends通配符 如果需要写入T,它是消费者(Consumer),要使用super通配符

泛型没有继承概念 上限: ? extends E 代表使用的泛型只能是E类型的子类/本身 下限: ? super E 代表使用的泛型只能是E类型的父类/本身

public class Collections {
    public static <T> void copy(List<? super T> dest, List<? extends T> src) {
        for (int i=0; i<src.size(); i++) {
            T t = src.get(i); // src是producer
            dest.add(t); // dest是consumer
        }
    }
}

extends 通配符可以读,不能写

限定T类型, 使用类似<T extends Number>定义泛型类时表示 泛型类型限定为Number以及Number的子类

方法内部可以调用获取Number引用的方法,例如:Number n = obj.getFirst(); 方法内部无法调用获取Integer引用的方法(Object除外),例如:Integer n = obj.getFirst();

public class Pair<T extends Number> { ... }

Pair<Number> p1 = null;
Pair<Integer> p2 = new Pair<>(1, 2);
Pair<Double> p3 = null;

super 通配符不可以读,能写

<? super Integer>通配符作为方法参数时表示:

方法内部可以调用传入Integer引用的方法,例如:obj.setFirst(Integer n); 方法内部无法调用获取Integer引用的方法(Object除外),例如:Integer n = obj.getFirst();

无限定通配符 既不能读,也不能写

无限定通配符<?>很少使用,可以用<T>替换,同时它是所有<T>类型的超类 只能做一些null判断

因为<?>通配符既没有extends,也没有super,因此: 不允许调用set(T)方法并传入引用(null除外); 不允许调用T get()方法并获取T引用(只能获取Object引用)

static boolean isNull(Pair<?> p) {
    return p.getFirst() == null || p.getLast() == null;
}

大多数情况下,可以引入泛型参数<T>消除<?>通配符

static <T> boolean isNull(Pair<T> p) {
    return p.getFirst() == null || p.getLast() == null;
}

泛型数组

如果在方法内部创建了泛型数组,最好不要将它返回给外部使用 部分反射API是泛型,例如:Class<T>,Constructor<T> 可以通过Array.newInstance(Class<T>, int)创建T[]数组,需要强制转型 同时使用泛型和可变参数时需要特别小心

变参数创建泛型数组T[]

public class ArrayHelper {
    @SafeVarargs
    static <T> T[] asArray(T... objs) {
        return objs;
    }
}

String[] ss = ArrayHelper.asArray("a", "b", "c");
Integer[] ns = ArrayHelper.asArray(1, 2, 3);
经验分享 程序员 微信小程序 职场和发展