摘自:HERE
理解Java泛型最简单的方法是把它看成一种便捷语法,能节省你某些Java类型转换(casting)上的操作:
List <Apple> box = ...; Apple apple = box.get(0);
上面的代码自身已表达的很清楚:box是一个装有Apple对象的List。get方法返回一个Apple对象实例,这个过程不需要进行类型转换。没有泛型,上面的代码需要写成这样:
List box = ...; Apple apple = (Apple) box.get(0);
很明显,泛型的主要好处就是让编译器保留参数的类型信息,执行类型检查,执行类型转换操作:编译器保证了这些类型转换的绝对无误。
泛型包含一个或多个类型参数。
类型参数不能使基本类型。
泛型的构成:
泛型类声明
泛型接口声明
泛型方法声明
泛型构造器(constructor)声明
泛型类和接口:如果一个类或接口上有一个或多个类型变量,那它就是泛型。类型变量由尖括号界定,放在类或接口名的后面:
public interface List<T> extends Collection<T> { ... }
泛型方法和构造器(Constructor):
public static <t> T getFirst(List<T> list)
这个方法将会接受一个List<T>类型的参数,返回一个T类型的对象。
例子
你既可以使用Java类库里提供的泛型类,也可以使用自己的泛型类。
类型安全的写入数据…
下面的这段代码是个例子,我们创建了一个List<String>实例,然后装入一些数据:
List<String> str = new ArrayList<String>(); str.add("Hello "); str.add("World.");
如果我们试图在List<String>装入另外一种对象,编译器就会提示错误:
str.add(1); //不能编译
类型安全的读取数据…
当我们在使用List<String>对象时,它总能保证我们得到的是一个String对象:
String myString = str.get(0);
遍历
类库中的很多类,诸如Iterator<T>,功能都有所增强,被泛型化。List<T>接口里的 iterator()方法现在返回的是Iterator<T>,由它的T next()方法返回的对象不需要再进行类型转换,你直接得到正确的类型。
for (Iterator<String> iter = str.iterator(); iter.hasNext();) { String s = iter.next(); System.out.print(s); }
向上造型一个泛型对象的引用(Covariance,协变)
例如,假设我们有很多箱子,每个箱子里都装有不同的水果,我们需要找到一种方法能够通用的处理任何一箱水果。更通俗的说法,A是B的子类型,我们需要找到一种方法能够将C<A>类型的实例赋给一个C<B>类型的声明。
为了完成这种操作,我们需要使用带有通配符的扩展声明,就像下面的例子里那样:
List<Apple> apples = new ArrayList<Apple>(); List<? extends Fruit> fruits = apples;
“? extends”是泛型类型的子类型相关性成为现实:Apple是Fruit的子类型,List<Apple> 是 List<? extends Fruit> 的子类型。
向下造型一个泛型对象的引用(Contravariance,逆变)
现在我来介绍另外一种通配符:? super。如果类型B是类型A的超类型(父类型),那么C<B> 是 C<? super A> 的子类型:
List<Fruit> fruits = new ArrayList<Fruit>(); List<? super Apple> = fruits;
-------------------------------------------------------------
摘录自这里,本篇文章只是简单地记录一些自己从中看到的东西。
泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。
泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在一个高得多的程度上验证类型假设。没有泛型,这些假设就只存在于程序员的头脑中(或者如果幸运的话,还存在于代码注释中)。
泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。
该代码不使用泛型:
List li = new ArrayList(); li.add(new Integer(3)); Integer i = (Integer) li.get(0);
该代码使用泛型:
List<Integer> li = new ArrayList<Integer>(); li.add(new Integer(3)); Integer i = li.get(0);
在简单的程序中使用一次泛型变量不会降低罗嗦程度。但是对于多次使用泛型变量的大型程序来说,则可以累积起来降低罗嗦程度。