文档章节

【java基础(五十)】为什么要使用泛型程序设计

o
 osc_qcm2mqmy
发布于 07/04 17:19
字数 1427
阅读 40
收藏 0

行业解决方案、产品招募中!想赚钱就来传!>>>

从Java程序设计语言1.0版发布以来,变化最大的部分就是泛型。致使Java SE 5.0中增加泛型机制的主要原因是为了满足1999年制定的最早的Java规范需求之一(JSR 14)。专家组花费了5年左右的时间用来定义规范和测试实现。

泛型正是我们需要的程序设计手段。使用泛型机制编写的程序代码要比那些杂乱地使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性。泛型对于集合类尤其有用。

为什么要使用泛型程序设计

泛型程序设计(Generic programming)意味着编写的代码可以被很多不同类型的对象所重用。例如,我们并不希望为聚集String和File对象分别设计不同的类。实际上,也不需要这样做。因为一个ArrayList类可以聚集任何类型的对象。这是一个泛型程序设计的实例。

实际上,在Java增加泛型类之前已经有一个ArrayList类。下面来研究泛型设计的机制是如何演变的,另外还会讲解这对于用户和实现着来说意味着什么。

类型参数的好坏

在Java中增加泛型类之前,泛型程序设计是用继承实现的。ArrayList类只维护一个Object引用的数组:

public class ArrayList {
	private Object[] elementData;
	...
	public Object get(int i) {...}
	public void add(Object o) {...}
}

这种方法有两个问题。当获取一个值时必须进行强制类型转换。

ArrayList files = new ArrayList();
...
String filename = (String)file.get(0);

此外,这里如果没有错误检查。可以向数组列表中添加任何类的对象。

files.add(new File("..."));

对于这个调用,编译和运行都不会出错。然而在其他地方,如果将get的结果强制类型转换为String类型,就会产生一个错误。

泛型提供了一个更好的解决方案:类型参数(type parameters)。ArrayList类有一个类型参数来指示元素的类型:

ArrayList<String> files = new ArrayList<>();

编译器也可以很好的利用这个信息。当调用get的时候,不需要进行强制类型转换,编译器就知道返回值类型为String,而不是Object:

String filename = files.get(0);

编译器还知道ArrayList<String>中add方法有一个类型为String的参数。这将比使用Object类型的参数安全一些。现在,编译器可以进行检查,避免插入错误类型的对象。如:

files.add(new File("..."));	// 这里将无法通过编译

是无法通过编译的。出现编译错误比类在运行时出现类的强制类型转换异常要好得多。

类型参数的魅力在于:使得程序具有更好的可读性和安全性。

泛型程序设计的能力级别

使用想ArrayList的泛型类很容易。大多数Java程序员都使用ArrayList<String>这样的类型,就好像他们已经构建在语言之中,像String[]数组一样。

但是,实现一个泛型并没还有那么容易。对于类型参数,使用这段代码的程序员可能想要内置(plug in)所有的类。他们希望在没有过多的限制以及混乱的错误消息的状态下,做所有的事情。因此,一个泛型程序员的任务就是预测出所有类的未来可能有的所有用途。

这一任务难到什么程度呢?下面是标准类库的设计者们肯定产生争议的一个典型问题。ArrayList类有一个方法addAll用来添加另一个集合的全部元素。程序员可能想要将ArrayList<Manage>中的所有元素添加到ArrayList<Employee>中去。然而,反过来就不行了。如何只能允许前一个调用,而不能允许后一个调用呢?Java语言的设计者发明了一个具有独特性的性概念,通配符类型(wildcart type),它解决了这个问题。通配符类型非常抽象,然而,他们能让库的构建者编写出尽可能灵活的方法。

泛型程序设计划分为3个能力级别。基本级别是,仅仅使用泛型类,典型的是想ArrayList这样的集合,不必考虑他们的工作方式与原因。大多数应用程序猿将会停留在这一级别上,知道出现了什么问题。当把不同的泛型类混合在一起时,或是在于对类型参数一无所知的遗留的代码进行衔接时,可能会看到含糊不清的错误消息。如果这样的话,就需要学习Java泛型来系统地解决这些问题,而不要胡乱地猜测。当然,最终可能想要实现自己的泛型类与泛型方法。

应用程序猿很可能不喜欢编写太多的泛型代码。JDK开发人员已经做出了很大的努力,为所有的集合类提供了类型参数。凭经验来说,那些原本涉及许多来自通用类型(如Object或Comparable接口)的强制类型转换的代码一定会因使用类型参数而受益。

捐赠

若你感觉读到这篇文章对你有启发,能引起你的思考。请不要吝啬你的钱包,你的任何打赏或者捐赠都是对我莫大的鼓励。

o
粉丝 0
博文 72
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
浅入浅出Android(003):使用TextView类构造文本控件

基础: TextView是无法供编辑的。 当我们新建一个项目MyTextView时候,默认的布局(/res/layout/activity_main.xml)中已经有了一个TextView: <TextView 运行效果如下: 修改其文本内容...

樂天
2014/03/22
585
1
CDH5: 使用parcels配置lzo

一、Parcel 部署步骤 1 下载: 首先需要下载 Parcel。下载完成后,Parcel 将驻留在 Cloudera Manager 主机的本地目录中。 2 分配: Parcel 下载后,将分配到群集中的所有主机上并解压缩。 3 激...

cloud-coder
2014/07/01
6.8K
1
程序猿媛一:Android滑动翻页+区域点击事件

滑动翻页+区域点击事件 ViewPager+GrideView 声明:博文为原创,文章内容为,效果展示,思路阐述,及代码片段。文尾附注源码获取途径。 转载请保留原文出处“http://my.oschina.net/gluoyer...

花佟林雨月
2013/11/09
4.1K
1
代码生成器--Codgen

Codgen是一个基于数据库元数据模型,使用freemarker模板引擎来构建输出的代码生成器。freemarker的数据模型结构通常来说都是一个Map树状结构模型,codgen也不例外,它的数据模型这棵树的根节...

黄天政
2013/01/29
1.4W
2

没有更多内容

加载失败,请刷新页面

加载更多

Python安装第三方库太慢??

今天在升级下载Python第三方库的时候特别慢,最后去升级pip的时候竟然还time out了,哇心态炸了。 问题想清楚了该怎么解决呢? 咱们可以用国内的镜像源啊,于是我在网上搜了一下国内的镜像源...

不卖萌的邓肯
今天
0
0
C语言与C++常见面试题

本篇根据各个公司的面试问的常见问题进行总结。 公众号回复“面试”,获取pdf答案 1 变量的声明和定义有什么区别 2 简述 #ifdef、#else、#endif和 #ifndef的作用 3 写出 int 、bool、 float、...

公众号C语言与CPP编程
今天
0
0
自定义CheckBox快速实现开发

在开发CheckBox过程中,经常感觉功能很简单,就是写了半天代码,尤其是设置监听和判断上,万一有10个以上的CheckBox,还会在复制时由于不小心,出现bug 天啦,这么简单常用的控件出BUG,简直没...

osc_gzy9w31p
18分钟前
0
0
写给小白看的线程和进程,高手勿入

计算机的核心是CPU,它承担了计算机的所有计算任务,CPU就像一个工厂,时刻在运行着,而操作系统管理着计算机,负责任务的调度、资源的分配和管理。 进程和线程都是计算机操作系统中的基本概...

hzjjames
今天
0
0
分布式锁,redisson是如何解决死锁问题

点击上方“小罗技术笔记”,关注公众号 第一时间送达实用干货 作者:雨点的名字 来源:http://suo.im/6748UQ 使用redis做分布式锁时大家可能都知道使用setnx容易发生死锁情况,大多数都会推荐...

javaNode
昨天
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部