近期看了《深入理解Java虚拟机》中对语法糖、泛型(称伪泛型)的一些介绍,顺便总结梳理一下以前对JDK1.5引入的泛型的理解与使用。
为何会引入泛型
|
|
上面这段代码,稍微有点经验,都知道会抛异常java.lang.ClassCastException。但是抛异常的时机却是在运行期。JVM在编译这段代码时,是可以通过的。tools.getObj()获取到对象时,需要程序员手动进行类型转换。这是早期关于Object做法。所以,泛型有了它的用武之地。
泛型类
|
|
utils1.getObject()时不用进行类型强转。因为它的类型是在new Utils
直接在编译期就进行了安全提示。
泛型方法
|
|
泛型方法,它的类型是调用方法时,由实参决定的。
泛型类,泛型方法
|
|
实际运行结果如下:
show()方法的类型是跟着Demo上面定义的T走的,所以可以隐藏该方法的泛型。
print()方法的类型是由实参决定的。
say()方法的类型也是由实参决定的。
关于泛型的总结
- 用于解决安全问题,是一个安全机制。类型安全机制。
- 将运行时期出现的问题java.lang.ClassCastException转移到了编译期。
- 避免强制类型转换的麻烦。
- 泛型的类型必须为引用类型,不能是基本类型。
什么时候定义泛型
- 当类中要操作的引用数据类型不确定的时候,早期定义Object来完成扩展,现在定义泛型来完成扩展。
- 泛型类定义的泛型,在整个类中有效。如果该泛型被方法使用,那么泛型类的对象在明确要操作的具体类型后,该方法要操作的数据类型就已经固定了。
- 为了让不同的方法可以操作不同类型,而且类型不确定。那么可以将泛型定义在方法上。
- 静态方法是不可以访问类上定义的泛型。如果静态方法操作的数据类型不确定,可以将泛型定义在该方法上。
- 泛型类每次都是在建立对象时才会被明确,由对象带着类型去运行。
实际使用场景一
|
|
使用静态泛型方法把request中的请求参数,通过反射+BeanUtils,直接封装成对象并返回。
实际使用场景二
|
|
使用工厂设计模式+泛型方法。
实际使用场景三
|
|
在new DemoDao的时候,DemoDao继承基类中的findAll()方法就明确是操作Demo这种类型的数据了。
泛型中的通配符与限定(用于泛型扩展)
- ?通配符,可以理解为占位符。?表示不确定类型。T表示为具体类型,传什么就是什么类型。
- ? extends E:表示可以接收E类型或者E类型的子类型。称为泛型的上限。
- ? super E:表示可以接收E类型或者E类型的父类型。称为泛型的下限。