什么时候使用泛型方法,什么时候使用类型通配符呢?一般能够使用通配符,都可以改写为泛型方法。

public interface Collection<E> extends Iterable<E> {
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
}

public interface Collection<E> extends Iterable<E> {
    <T> boolean containsAll(Collection<T> c);
    <T extends E> boolean addAll(Collection<T> c);
}

这两个方法的类型形参T其实都只使用了一次,唯一效果就是在调用时传入实际类型参数,因此Collection接口设计时采用的时上示第一种:类型通配符,类型通配符就是被设计来支持灵活子类化的。

泛型方法用来表示方法一个或者多个参数之间的依赖关系,或者参数与返回值的关系,如果没有这种依赖关系,就不要使用泛型方法。

有时候会同时使用泛型通配符和泛型方法。比如Collctions.copy()方法。dest和src的参数之间存在依赖关系:src的集合元素必须是dest类型或其子类,故用泛型方法表示dest的类型,而该方法无需向src中添加修改元素,也没有其它参数src的类型,因此使用通配符更合适。

 public static <T> void copy(List<? super T> dest, List<? extends T> src) {...}