继上一文《java泛型的学习笔记[1]—基础知识》之后,本文将介绍泛型的一些应用和应用过程中遇到的问题。
在此之前,我们先给出一张类图:
1)泛型类型的子类型问题
我们首先来看这样一句代码。该行代码正确,因为Cat是Animal的子类型
Animal animal=new Cat();//
但是再看下一句代码:
AarrayList<Animal> animals=new ArrayList<Cat>();//编译出错
这句代码编译出错,因为虽然因为Cat是Animal的子类型,但是: ArrayList<Cat>不是AarrayList<Animal>的子类型。
如果深究起来,只能说ArrayList<Cat>是List<Cat>的子类型。而ArrayList<Cat>与AarrayList<Animal>是两个不兼容的类型,或者说是两个没有关系的类型。
2)通配符的使用问题
我们先来看看两段编译出错的代码。其
1.ArrayList<?> list=new ArrayList<Cat>();
list.add(new Cat());//编译出错
2.ArrayList<? extends Animal> list=new ArrayList<Cat>();
list.add(new Cat());//编译出错
出错的原因或许大家能想明白:使用了"?"或者"? extends Animal"的通配符,我们不确定“?”代表的类型。比如ArrayList<? extends Animal>,通配符可能代表的类型包括:Animal,Cat或Dog,还有SmallCat。若是“?”表示Dog,而这里的list.add(new Cat())肯定会出错,即?表示的类型与你想要添加数据的类型,可能是不兼容的。对于ArrayList<?>,其实也相当于ArrayList<?
extends Object>。所以1 和2 用法本质上是相同的。
因此,为了消除不确定性,为了确保类型安全,对于使用"? extends"通配符的数据结构,都不允许往其中添加任何的值了。
那么对于“? super ”类型的情况呢?
比如:
ArrayList<? super Cat> list=new ArrayList<Cat>();
list.add(new Cat());//
list.add(new SmallCat());//
以上三句代码就是正确的。
为什么会这样呢?原理其实不难:因为使用了"? super Cat"后,虽然“?”也充满了不确定性,包括:Cat,Animal,还有Object。但是其中却有一条确定性:Cat与SmallCat一定与?兼容。因为?可能的最底层次就是Cat,也就是说Cat和SmallCat一定是?本身的类型或?的子类型。这时,list.add(new Cat());与list.add(new SmallCat());当然是是能保证正确的。
3)泛型在SSH框架中的运用
在ssh中,一般我们会自定义一些基类,对我们项目中的一些功能或代码进行封装。比如,我们通常会定义Dao层的基类,Service层的基类,还有Action的基类 等
等。
以DAO层为例,在做项目的时候每次都为每个POJO实体写一个对应的DAO很麻烦,虽然可以由IDE或者一些快速生成工具来生成,但是也难免需要更改。基于此
原因,一般我们需要定义一个通用的泛型DAO来封装一些最基本的操作,包括对实体的增删改查等。这样就大大简化了代码,也保证了DAO层在使用时的类型安全。
OK,本文就到这里吧。欢迎各位参与讨论和补充内容。