1、为什么要使用泛型
这里我们俩看一段代码;
List list = new ArrayList(); list.add("CSDN_SEU_Cavin"); list.add(100); for (int i = 0; i < list.size(); i++) { String name = (String) list.get(i); //取出Integer时,运行时出现异常 System.out.println("name:" + name); }
本例向list类型集合中加入了一个字符串类型的值和一个Integer类型的值。(这样合法,因为此时list默认的类型为Object类型)。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他原因,运行时会出现java.lang.ClassCastException异常。为了解决这个问题,泛型应运而生。
2、泛型的使用
泛型让编程人员能够使用类型抽象,通常用于集合里面。
List<String> list = new ArrayList<String>();
这里这样写,上面那段循环取值得方式就不会报错,而且也不需要进行类型的强制转换。通过List<String>,直接限定了list集合中只能含有String类型的元素。
3、泛型只在编译期间有效
我们在使用泛型的时候也要了解到泛型的编译时怎样的,因此在这里,我们需要特别的注意是:泛型,只是在代码编译成class文件期间有效
AyyayList<String> a = new ArrayList<String>(); ArrayList b = new ArrayList(); Class c1 = a.getClass(); Class c2 = b.getClass(); System.out.println(a == b);
上面程序的输出结果为true。是因为所有反射的操作都是在运行时进行的,既然为true,就证明了编译之后,程序会采取去泛型化的措施。
也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,成功编译过后的class文件中是不包含任何泛型信息的。泛型信息不会进入到运行时阶段。
下面这段代码通过Java的反射机制很好的解释了泛型只在编译期间有效
ArrayList<String> a = new ArrayList<String>(); a.add("CSDN_SEU_Cavin"); Class c = a.getClass(); try{ Method method = c.getMethod("add",Object.class); method.invoke(a,100); System.out.println(a); //[CSDN_SEU_Cavin, 100]
}catch(Exception e){
e.printStackTrace();
}
4、泛型类和泛型方法
public static class FX<T> { private T ob; // 定义泛型成员变量 public FX(T ob) { this.ob = ob; } public T getOb() { return ob; } public void showTyep() { System.out.println("T的实际类型是: " + ob.getClass().getName()); } } public static void main(String[] args) { FX<Integer> intOb = new FX<Integer>(100); intOb.showTyep(); System.out.println("value= " + intOb.getOb()); //java.lang.Integer System.out.println("----------------------------------"); FX<String> strOb = new FX<String>("CSDN_SEU_Calvin"); strOb.showTyep(); System.out.println("value= " + strOb.getOb()); //value= 100 }
5.泛型的好处
(1)类型安全。
通过知道使用泛型定义的变量的类型限制,编译器可以更有效地提高Java程序的类型安全。
(2)消除强制类型转换。
消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。所有的强制转换都是自动和隐式的。
(3)提高性能
6.泛型使用的注意事项
(1)泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
(2)泛型的类型参数可以有多个。
(3)不能对确切的泛型类型使用instanceof操作。如下面的操作是非法的,编译时会出错。
(4)不能创建一个确切的泛型类型的数组。