1.何为泛型:
泛型:jdk 1.5 的新特性,是对java语言的一种扩展,以支持创建可以按类弄进行参数化的类。在jdk1.5以前的集合中可以放入任何类型。这就导致了在取出数据的时候需要进行各种的强制转换。这就增加了程序员的负担。
所以后在jdk.1.5的集合类希望你在定义集合时,明确表示你要向集合中装入哪种数据,无法去装入指定类型以外的数据。
ArrayList<Integer> list= new ArrayList<Integer>();
这样就表示了在list中只能去定义Integer类型的数据,在定义其它类型的数据的时候就会去报错。
2. 泛型的意义
java中的泛型只是去给编译器看的。用来限定集合中的输入类型,限制非法输入,而且所有的强制转换都是隐式的。但是在运行时,JVM 会进行去掉这些类型信息。这样就不会去影响效率。
3.泛型的注意事项
1)泛型是给编译器看的,在运行时会去类型信息。如下用反射得到集合中的方法:
List<Integer> collection1 = new ArrayList<Integer>(); collection1.getClass().getMethod("add",Object.class).invoke(collection1, "yangzhi"); System.out.println(collection1.get(0));
这就可以去利用发射得到集合类的字节码,然后调用其方法去实现增加数据,这里就是在运行是才去添加数据。那么因为泛型是给编译器看,那么即使泛型是定义的Integer数据,但是在运行时是可以去加入任意的。
2)泛型中的参数化类型不考虑继承关系。
//Vector<String> vector = new Vector<Object>(); //报错 //Vector<Object> vector = new Vector<String>(); //报错
3)在创建数组实例时,数组的元素不能参数化类型,例如下面的语句有错误:
//Vector<Integer> vectorList[] = new Vector<Integer>[10]; //报错
4)只有引用类型才能做为泛型方法的实际参数。
public static void main(String[] args) { // TODO Auto-generated method stub swap(new String[]{"123","344"},1,2); add(3,5); //swap(int[]{1,2,2},1,2); } public static <T> void swap(T[] t ,int a , int b){ T tmp = t[a]; t[a] = t[b]; t[b] = tmp; } public static <T> void add(T a,T b){ }
而在上面的add方法中,int类型的3,5之所以会能传入进去。是因为进行了自动的装箱操作。但是下面的swap函数会报错,是因为传入的int[] 是一个数组,new int[3] 本身就是一个对象,你想要的有可能就是int数组呢。这装箱岂不是弄巧成拙。 所以它不会对其中的数据进行装箱操作。故而下面的swap(int[]{1,2,2},1,2);语句就会报错。
5)泛型中的?通配符。使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,不能调用与参数化有关的方法。
6)通配符可以限制向上限制和向下限制。如下:
/** * 表示传入的参数化类型只局限于Number或者Number的子类。 * */ public static void printCollentction2(Collection<? extends Number> collection){ } /** * 表示传入的参数化类型只局限于Number或者Number的父类。 * */ public static void printCollentction3(Collection<? super Number> collection){ } /**注意:限定符部是包括自己。**/
7)泛型类定义:如下:
public class GenericDao<T> { public void add(T x){ } public T findById(int id){ return null; } /** * 静态方法不能使用泛型。 * ****/ //public static void test(T name){ //} }
可以有多个泛型参数,中间用逗号隔开,还可以定义泛型接口,泛型方法。这些都泛型类中泛型的使用规则类似。