前面从泛型方法的用法介绍到了泛型的起源,既然单个方法允许拥有泛化的参数类型,那么一个类也应当支持类级别的泛化类型,例如各种容器类型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开发笔记(序)章节目录

Java开发笔记(六十九)泛型类的定义及其运用的更多相关文章

  1. Java开发笔记(十九)规律变化的for循环

    前面介绍while循环时,有个名叫year的整型变量频繁出现,并且它是控制循环进出的关键要素.不管哪一种while写法,都存在三处与year有关的操作,分别是“year = 0”.“year<l ...

  2. Java开发笔记(九十九)定时器与定时任务

    前面介绍了线程的几种运行方式,不管哪种方式,一旦调用了线程实例的start方法,都会立即启动线程的事务处理.然而某些业务场景在事务执行时间方面有特殊需求,例如期望延迟若干时间之后才开始事务运行,又如期 ...

  3. Java开发笔记(十六)非此即彼的条件分支

    前面花了大量篇幅介绍布尔类型及相应的关系运算和逻辑运算,那可不仅仅是为了求真值或假值,更是为了通过布尔值控制流程的走向.在现实生活中,常常需要在岔路口抉择走去何方,往南还是往北,向东还是向西?在Jav ...

  4. .Net开发笔记(十九) 创建一个可以可视化设计的对象

    阅读本篇博客之前需要了解VS窗体设计器的工作原理,详细可参见本系列博客(十).(十一).(十二).必须需要知道的一条结论就是:处于窗体设计器(Form Designer)中的任何组件(包含控件,下同) ...

  5. Java学习笔记(十九)——Java 日志记录 AND log4j

    [前面的话] 学习的进度应该稍微在快一点. Java日志到了必须学习怎么使用的时候了,因为在项目中要进行使用.基础性文章,选择性阅读. [结构] java日志对调试,记录运行,问题定位都起到了很重要的 ...

  6. 【Java学习笔记之十九】super在Java继承中的用法小结

    1)有人写了个很好的初始化属性的构造函数,而你仅仅想要在其中添加另一些自己新建属性的初始化,这样在一个构造函数中调用另外一个构造函数,可以避免重复的代码量,减少工作量: 2)在一个构造函数中调用另外一 ...

  7. Java开发笔记(十)一元运算符的技巧

    前面讲到赋值运算符的时候,提到“x = x+7”可以被“x += 7”所取代,当然Java编程中给某个变量自加7并不常见,常见的是给某变量自加1,就像走台阶,一般都是一级一级台阶地走,犯不着一下子跳上 ...

  8. Java开发笔记(十二)布尔变量论道与或非

    在编程语言的设计之初,它们除了可以进行数学计算,还常常用于逻辑推理和条件判断.为了实现逻辑判断的功能,Java引入了一种布尔类型boolean,用来表示“真”和“假”.该类型的变量只允许两个取值,即t ...

  9. Java开发笔记(十四)几种运算符的优先级顺序

    到目前为止,我们已经学习了Java语言的好几种运算符,包括算术运算符.赋值运算符.逻辑运算符.关系运算符等基础运算符,并且在书写赋值语句时都没添加圆括号,显然是默认了先完成算术.逻辑.关系等运算,最后 ...

  10. Java开发笔记(十五)短路逻辑运算的优势

    前面提到逻辑运算只能操作布尔变量,这其实是不严谨的,因为经过Java编程实现,会发现“&”.“|”.“^”这几个逻辑符号竟然可以对数字进行运算.譬如下面的代码就直接对数字分别开展了“与”.“或 ...

随机推荐

  1. 03-es6语法 Promise 和 es8语法 async await 的了解和基本使用

    //Promise // 1.说明 : Promise 是 es6 中提出的新语法 // 2.作用 : 用 '用户编写同步代码' 的方式 '处理异步' 的一种解决方案 // 3.以前 : 处理异步 , ...

  2. SQL插入数据--数据中的某一列来自本表中的数据

    背景: 项目初期使用的配置库和业务库两种数据库并行,所有配置数据位于配置库,所有业务数据根据不同省份位于不同数据库.由于使用省份越来越多,各省的配置数据也越来越多导致配置库的数据量过于庞大,各省共用一 ...

  3. Socket看法

    Socket通常也称做”套接字“,用于描述IP地址和端口,废话不多说,它就是网络通信过程中端点的抽象表示. Socket又称"套接字",应用程序通常通过"套接字" ...

  4. SQLite异常 qAdmin: Cannot perform this operation on a closed dataset.【申明:来源于网络】

    SQLite异常 qAdmin: Cannot perform this operation on a closed dataset. 当使用 SQLite administrator,打开SQLit ...

  5. Foxmail6.5 ERR LOGIN FAIL 重新输入口令

    这几天 Foxmail 6.5 收邮件不正常,一直报告ERR LOGIN FAIL,要求重新输入口令. 但输入正确的口令也无法收邮件. 反复折腾,最后发现如下设置即可: 邮箱账户设置 --> 邮 ...

  6. Oracle客户端、服务的安装及干净卸载Oracle

    软件下载地址: 链接:https://pan.baidu.com/s/1Sluf890eNuaV8muL55eO2w 提取码:oez7 服务端因文件过大,所以分了两个文件压缩包,下载后将内容解压后放置 ...

  7. [Swift]LeetCode461. 汉明距离 | Hamming Distance

    The Hamming distance between two integers is the number of positions at which the corresponding bits ...

  8. [Swift]LeetCode581. 最短无序连续子数组 | Shortest Unsorted Continuous Subarray

    Given an integer array, you need to find one continuous subarray that if you only sort this subarray ...

  9. [Swift]LeetCode743. 网络延迟时间 | Network Delay Time

    There are N network nodes, labelled 1 to N. Given times, a list of travel times as directededges tim ...

  10. [Swift]LeetCode879. 盈利计划 | Profitable Schemes

    There are G people in a gang, and a list of various crimes they could commit. The i-th crime generat ...