前面从泛型方法的用法介绍到了泛型的起源,既然单个方法允许拥有泛化的参数类型,那么一个类也应当支持类级别的泛化类型,例如各种容器类型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. 巧用PHP中__get()魔术方法

    PHP中的魔术方法有很多,这些魔术方法可以让PHP脚本在某些特定的情况下自动调用.比如 __construct() 每次实例化一个类都会先调用该方法进行初始化.这里我们讲一下__get() 魔术方法的 ...

  2. eclipse上的maven,添加依赖后无法自动下载相应的jar包

    报错信息: Failed to read artifact descriptor for org.quartz-scheduler:quartz-jobs:jar:2.2.3  org.eclipse ...

  3. 微信小程序学习笔记(三)

    一般setData方法多用于点击后改变页面信息或者刷新后与后台交互获取最新的信息 注意: 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致 ...

  4. json转义 使用 JavaScriptSerializer 时 需要添加的引用

    当创建JavaScriptSerializer创建对象时,JavaScriptSerializer jss=new JavaScriptSerializer():时. 1.   需要添加的是Syste ...

  5. 熟悉HBase基本操作

    1. ssh localhost start-dfs.sh start-hbase.sh hbase shell create 'Student', 'S_No', 'S_Name', 'S_Sex' ...

  6. MySQL 千万级 数据库或大表优化

    首先考虑如下因素: 1.数据的容量:1-3年内会大概多少条数据,每条数据大概多少字节: 2.数据项:是否有大字段,那些字段的值是否经常被更新: 3.数据查询SQL条件:哪些数据项的列名称经常出现在WH ...

  7. 【计算机篇】Office 2016 for Mac 安装和破解教程

    免责声明 请亲们支持正版.这教程旨在分享,供参考. 为啥写这篇文章 对于大多数使用 Mac 的用户而言,虽然有苹果自家的办公软件,但功能少,用起来不舒服.而 Offer 2016 版的需要登录激活购买 ...

  8. Java堆和栈的区别和介绍,JVM的堆和栈

    一.Java的堆内存和栈内存 Java把内存划分成两种:一种是堆内存,一种是栈内存.   堆:主要用于存储实例化的对象,数组.由JVM动态分配内存空间.一个JVM只有一个堆内存,线程是可以共享数据的. ...

  9. CSS怎么在项目里引入自定义字体(@font-face)

    前言: 以前我一直用内置的默认字体给文字设置字体,直到一天UI妹纸给了我下面的字体    当时我是蒙蔽的,这个字体的效果如下 默认字体并无该字体,直接设置是没有效果的,这时就需要用到自定义字体了 下面 ...

  10. [Swift]LeetCode169. 求众数 | Majority Element

    Given an array of size n, find the majority element. The majority element is the element that appear ...