前面从泛型方法的用法介绍到了泛型的起源,既然单个方法允许拥有泛化的参数类型,那么一个类也应当支持类级别的泛化类型,例如各种容器类型ArrayList、HashMap等等。一旦某个类的定义代码在类名称后面添加“<T>”这种泛型声明,该类就变成了泛型类(也称模板类)。况且泛型类不单单支持一种泛型参数,还支持同时声明多种泛型参数,像“<T>”表示当前类存在唯一一种泛型参数;若想声明当前类拥有两种泛型参数,则可使用“<T, R>”这种以逗号隔开的泛型列表;同时声明三种泛型参数的话,尖括号内的泛型列表就有三个参数,形如“<U, V, W>”这般;至于更多种泛型参数的声明方式可依此类推。
在泛型类的内部代码中,事先已经声明的泛型可以拿来直接使用,无需在成员方法前面额外添加“<T>”。除此之外,在类代码中使用泛型T就跟使用普通类型一样,可以用它来创建泛型实例,可以用它表示输入参数的类型,也可以用它表示输出参数的类型。举个泛型类的简单应用例子,现在准备利用清单List来保存数据,然后想获取这组数据当中最长的元素,以及最短的元素。按照前述需求,划分该泛型类应当具备的功能,初步罗列包括以下几点:
1、泛型类要声明一个泛型参数“<T>”,用于给清单需要的元素类型占位;
2、定义泛型类的构造方法,传入待保存的清单对象,其中对象类型为“List<T>”;
3、定义getMaxLengthItem方法,用于获取长度最大的清单元素,注意该方法的输出参数类型为T;
4、定义getMinLengthItem方法,用于获取长度最小的清单元素,该方法的输出参数类型也为T;
根据上面的几点功能要求,编码实现的泛型类代码示例如下:
//定义简单的泛型清单。 //类名后面添加“<T>”,表示该类的内部代码中,所有的T类型都为外部需要时再指定的泛型。 //如果泛型不止一个,则用逗号隔开,比如两个泛型可用“<T, R>”。 public class SimpleList<T> { private List<T> list; // 清单。注意清单元素的数据类型为泛型T // 构造方法,传入要保存的清单数据 public SimpleList(List<T> list) { this.list = list; } // 获取当前保存的清单数据 public List<T> getData() { return this.list; } // 获取长度最大的清单元素。注意这里的返回数据为泛型T public T getMaxLengthItem() { if (list == null || list.size() <= 0) { return null; } T t = list.get(0); // 利用T声明了一个泛型变量t for (int i = 0; i < list.size(); i++) { if (list.get(i).toString().length() > t.toString().length()) { t = list.get(i); } } return t; } // 获取长度最短的清单元素。注意这里的返回数据为泛型T public T getMinLengthItem() { if (list == null || list.size() <= 0) { return null; } T t = list.get(0); // 利用T声明了一个泛型变量t for (int i = 0; i < list.size(); i++) { if (list.get(i).toString().length() < t.toString().length()) { t = list.get(i); } } return t; } }
从这个泛型类的代码可知,泛型T犹如系统自带的数据类型一般,它在泛型类内部的使用毫无障碍,你可以把它想象为Integer类型,或者Double类型。纵观整个泛型类的代码,唯有最开始的类名后面多了个“<T>”,其它地方跟普通类就没什么两样了。
外部调用泛型类的时候,可参照ArrayList、HashMap等容器类的用法,同样在类名后面添加形如“<具体的数据类型名称>”的模板。下面是段SimpleList的测试代码,先构造指定清单的泛型实例,再分别调用getMaxLengthItem与getMinLengthItem方法获取最长的元素和最短的元素,完整代码如下所示:
// 数组工具Arrays的asList方法可以把一系列元素直接赋值给清单对象 List<Double> doubleList = Arrays.asList(1.1, 2D, 3.1415926, 11.11); // 泛型实例的参数类型跟在类名称后面,以尖括号包裹 SimpleList<Double> simpleList = new SimpleList<Double>(doubleList); // 打印清单中最长的元素 System.out.println("simpleList.getMaxLengthItem()=" + simpleList.getMaxLengthItem()); // 打印清单中最短的元素 System.out.println("simpleList.getMinLengthItem()=" + simpleList.getMinLengthItem());
运行以上的测试代码,观察到下面的日志结果,可见泛型类SimpleList正确挑选出了最长的元素和最短的元素:
simpleList.getMaxLengthItem()=3.1415926 simpleList.getMinLengthItem()=1.1
更多Java技术文章参见《Java开发笔记(序)章节目录》