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);