一、泛型的主要优点是能在编译时检测出类型错误而不是在运行时检测出错误。
二、泛型类型必须是引用类型,即基本类型不能作为泛型类型。
三、定义泛型类、接口和方法
1.构造方法应该是public ClassName()而不是public ClassName<E>()
2.可以为静态方法定义泛型类型
声明泛型方法 public static <E> void methodName(E){}
调用泛型方法 method(params),编译器自动发现实际类型
四、通配泛型
1.<?>非受限通配 等价于 <? extends Object>
2.<? extends T> 表示T或T的子类
3.<? super T> 表示T或T的父类
注意: 虽然Integer是Object的子类,但是ClassName(Integer)并不是ClassName(Object)的子类!!
五、消除泛型和对泛型的限制
1.编译器使用泛型类型信息来编译代码, 但随后就会消除它,所以泛型信息在运行时是不可用的。例如:
ArrayList<String> list = new ArrayList(); list.add("abc") String state = list.get(0)
等价于
ArrayList list = new ArrayList(); list.add("abc") String state = (String)( list.get(0))
2.如果泛型类型是受限的,编译器会使用受限类型来替换它。例如:
public static <E extens SomeObject> boolean isEqual(E o1, E o2){ return o1.getArea() == o2.getArea() }
等价于
public static <SomeObject> boolean isEqual(SomeObject o1, SomeObject o2){ return o1.getArea() == o2.getArea() }
3.无论实际类型是什么,泛型类是被他的所有实例所共享的。例如:
ArrayList<String> list1 = new ArrayLsit(); ArrayList<Integer> list1 = new ArrayLsit();
在运行时只有一个ArrayList类加载到JVM中,而list1 instanceof ArrayList<String>是错误的,因为没有ArrayList<String>这个类加载到JVM中
4.因为泛型类型在运行时被消除,所以对使用泛型有一些限制:
I.不能new E(), 不能使用泛型类型参数创建实例
II.不能new E[], 不能使用泛型类型参数创建数组, 但可以E[] list = (E[])new Object[capacity]
III.静态上下文中不允许类的参数是泛型类型
public class Test <E>{ public static void m(E o1){} //illegal public static E o1; //illegal static{ E o1; //illegal }
IV.不能再异常类中使用泛型参数
public class MyException<E> extends Exception{} //illegal