为什么要深入一下泛型?
本人最近开始在深读一些源码,发现有些底层的一下设计理解的不是很透彻,很多优秀的框架用到了各种各样的设计模式外加一些泛型去实现,不审核将泛型进行理解,感觉总是一头雾水。
定义
聊到泛型,我们第一个想到的就是,这个东西到底是干什么的,我想很大一部分小伙伴应该也是仅仅停留在偶尔使用这个水平上面,至于再深入一些,估计能说出来的够呛。书上这么说,泛型,即“参数化类型”。说到参数,我们知道,定义方法的时候是形参,传递实参。那何为参数化类型?对比着上面的理解,其实也很容易,说白了就是将原来的类型进行参数化。操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
特性
泛型只在编译阶段有效。我们看下如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
public class GenericsDemo { public static void main(String[] args) { List stringArrayList = new ArrayList(); List integerArrayList = new ArrayList(); Class classStringArrayList = stringArrayList.getClass(); Class classIntegerArrayList = integerArrayList.getClass(); if(classStringArrayList.equals(classIntegerArrayList)){ System.out.println("泛型测试类型相同"); } } }
|
最终我们输出的结果是“泛型测试类型相同”(大家可以直接拷贝本人的代码去运行一下)。这个结果说明了什么呢?说明在编译之后程序会采取去泛型化的措施。明明是不同的类型,但是class字节码却是同一份。也就是说明在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦除,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。简而言之,泛型信息不会进入到运行时阶段。
使用
开头的时候我们提到了,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。那么我们就分别来看一下这三种场景下泛型的使用。
泛型类
上述例子提到的List,说白了就是一个泛型类。我们还是自己写一个,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
public class GenericsClassDemo<T> {
private T t;
GenericsClassDemo(T t){ this.t = t; } GenericsClassDemo(){ } public T getT() { return t; } public void setT(T t) { this.t = t; } }
|
调用函数:
1 2 3 4 5 6 7 8 9 10 11
| public class GenericsTestMain { public static void main(String[] args) { GenericsClassDemo stringGenericsClassDemo = new GenericsClassDemo("测试"); System.out.println(stringGenericsClassDemo.getT());
GenericsClassDemo integerGenericsClassDemo = new GenericsClassDemo(); integerGenericsClassDemo.setT(123); System.out.println(integerGenericsClassDemo.getT()); } }
|
输出结果,分别为:“测试”、“123”。