编程的时候,能在编译时发现并修改错误最好,等上线运行时报错才解决,则属于生产事故,且找到bug的位置需要花费更多的时间和精力。泛型是java1.5以后出的内容,运用泛型,指定集合中的对象类型,你可以在编译时发现类型不匹配的错误,并且取数据时不需要手动强转类型。

 

我们最常用的集合类之一便是List,假如我们想让这个List只放Integer类型的元素,可以这样创建集合类:

List<Integer>  list = new ArrayList<Integer>;
List.add(new Integer(88));

 

一般的编程工作中对泛型的运用也就仅此而已,但你若想让你的程序更加安全,更加清爽,必须深入理解知识点,挖掘泛型的潜能。在此我们就循序渐进,来了解下List在运行泛型后需要注意的四张面孔

List<Object>
   List
   List<?>
   List<E>

以下是示例代码,相关解释都在注释里面,大家可以把代码粘贴到eclipse上对照查看,效果更好   

 

import java.util.ArrayList;
import java.util.List;
 
public class KnowGeneric {
 
 private static void normAdd(List<Object> list, Object o) {
  list.add(o);
 }
 
 private static void rawAdd(List list, Object o) {
  list.add(o);
 }
 
 private static <E> void wildCardQueryAdd(List<?> list, Object o) {
  if (list.contains(o)) {
   System.out.println("contain");
  } else {
   System.out.println("not contain");
  }
 
  /*
   * list集合不能添加除null以外的任何元素。 
compile error The method add(capture#1-of ?) in the
   * type List<capture#1-of ?> is not applicable for the arguments (Object)
   */
  list.add(o);
  list.add(null);
 
 }
 
 private static <E> void geneAdd(List<E> list, E e) {
  list.add(e);
 }
 
 public static void main(String[] args) {
  List<Integer> numList = new ArrayList<Integer>();
  List<Object> objList = new ArrayList<Object>();
  // 编译通过
  normAdd(objList, new Object());
 
  // normAdd
 
  /*

   * normAdd中定义的方法参数是List<Object>类型,rawAdd中的是List原生类型,而List<Integer>是List的子类型,

   * 却不是List<Object>的子类型,因此报如下编译错误

    编译错误 The method normAdd(List<Object>, Object)

 

* in the type Know is not applicable for the arguments (List<Integer>,
   * Integer)
   */
  normAdd(numList, new Integer(88));
 
  // rawAdd
 
  numList.clear();
  objList.clear();
  rawAdd(objList, new Object());
  /*

   * 方法声明参数类型为原生类型list,元素类型信息被抹去,以下代码虽然编译通过,

   * 运行时却会报ClassCastException错误,所以尽量不要使用list原生类型,java保留原生类型主要是为了兼容1.5以前的代码。

* Exception in thread "main" java.lang.ClassCastException: java.lang.String
   * cannot be cast to java.lang.Integer
   */
 
  rawAdd(numList, "str");
  Integer num = numList.get(0);
 
  // geneAdd
 
  numList.clear();
  objList.clear();
  geneAdd(numList, new Integer(88));
  /*

   * 定义使用了泛型方法,编译时进行类型检查,添加字符串时会报编译错误。 compile error The method geneAdd(List<E>,

* E) in the type Know is not applicable for the arguments (List<Integer>,
   * String)
   */
  geneAdd(numList, "33");
 
  // wildCardQueryAdd
 
  numList.clear();
  objList.clear();
  /*

   * 前面讲了不要使用list原生类型,如果集合中元素类型未知或者无关紧要,则可以使用无界通配符List<?>,

     不像 normAdd(numList,new Integer(88));下面这段代码可以编译通过的,但是方法体中,numList集合不能添加除null以外的任何元素。

*/
  wildCardQueryAdd(numList, new Integer(33));
 
 }
 
}

 

也许大家有个疑问normAdd方法只能传List<Object>类型的参数,rawAdd方法又不建议使用,而wildCardQueryAdd方法中不能对集合添加除null以外的元素(使用场景有限),那该怎么办,上面代码中的泛型方法geneAdd是一个解决途径,另外就是有界通配符了,我们下回再讲。