首先拿java的List做一个例子:
public interface List <E> { void add(E x); Iterator<E> iterator(); } public interface Iterator<E> { E next(); boolean hasNext(); }
在上面的例子里,E被称为参数化类型:parameterized type,它可以被诸如Integer(类型参数,actual type argument)代替
public interface IntegerList { void add(Integer x); Iterator<Integer> iterator(); }另外的一个例子:public static void printCollection(List<Object> c) { for (Object e : c) { System.out.println(e); } }
public static void main(String[] args) { List<Integer>a=new ArrayList<Integer>(); a.add(2); a.add(1); printCollection(a); }
这是一个编译期便会出现问题的例子:上面的list只能接收Object,而它不是所有类型的list的父类于是在java的泛型中引入了? List<?> 意义为:list of unknown ,用它来做所有类型的List的父类。List<?>匹配所有类型的list,它被称为通配符,英文为 wildcard type。Collection<?> c = new ArrayList<String>(); c.add(new Object()); // Compile time error上面的collection便用到了通配符,但是当往collection里添加一个object时还是报错,官方给出的解释是:因为我们不知道c的类型到底是什么,所以我们不能往里添加任何的东西,因为我们add的任何参数都必须是?的子类。但是有一个例外:null.有限制的通配符: bounded wildcard比如 Circle extends Shape{}Rectangle extends Shape{}List<? extends Shape>即为一个有限制的通配符的例子,其中shape是? 的上限,upper bound泛型方法:static <T> void fromArrayToCollection(T[] a, Collection<T> c) { for (T o : a) { c.add(o); // Correct } }现在的问题是,什么时候用通配符? 什么时候用泛型方法T?官方文档的解释是这样的:Wildcards are designed to support flexible subtyping
Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn't such a dependency, a generic method should not be used.
也就是说,T这个泛型方法,需要用在有继承关系的地方,在Collections.copy中的方法:class Collections { public static <T> void copy(List<T> dest, List<? extends T> src) { ... }当然,官方推荐使用?:Using wildcards is clearer and more concise than declaring explicit type parameters, and should therefore be preferred whenever possible.
比如下面的这个例子:class Collections { public static <T, S extends T> void copy(List<T> dest, List<S> src) { ... }S只是用了一次,所以用?代替也无妨最后,? 的使用十分的灵活,它不单单只能使用在方法签名,还能用在数组,变量之中static List<List<? extends Shape>> history = new ArrayList<List<? extends Shape>>();泛型类被所有的调用方共享,无论类型参数是什么,在运行时的泛型类都有统一的类,于是就有了下面的结果:List <String> l1 = new ArrayList<String>(); List<Integer> l2 = new ArrayList<Integer>(); System.out.println(l1.getClass() == l2.getClass());返回TRUE哦在JDK5之后,java.lang.Class也变成了泛型。。。。。比如Class<T> 这个T表示的意思就是这个class object代表的类型,举个例子,String.class就是Class<String>