Java核心技术第12章(1)
2015-10-20 16:06
519 查看
第12章 泛型程序设计
使用泛型机制编写的程序代码要比那些杂乱地使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性.泛型对于集合类尤其有用.至少在表面上看来,泛型很像C++中的模板.与Java一样,在C++中,模板也是最先被添加到语言中支持强类型集合的.
12.1 为什么要使用泛型程序设计
泛型程序设计(Generic programming)意味着编写的代码可以被很多不同类型的对象所重用.例如,我们并不希望为聚集String和File对象分别设计不同的类.实际上,也不需要这样做,因为一个ArrayList类可以聚集任何类型的对象.这是一个泛型程序设计的实例.在Java中增加泛型类之前,泛型程序设计是用继承实现的.ArrayList类只维护一个Object引用的数组:
public class ArrayList // before generic classes { private Object[] elementData; ... public Object get(int i) { ... } public void add(Object o){ ... } }这样实现有两个问题.当获取一个值时必须进行强制类型转换.
ArrayList files = new ArrayList(); ... String filename = (String) files.get(0);此外,这里没有错误检查.可以向数组列表中添加任何类的对象.
files.add(new File("..."));对于这个调用,编译和运行都不会出错.然而在其他地方,如果将get的结果强制类型转换为String类型,就会产生一个错误.
泛型提供了一个更好的解决方法:类型参数(type parameters).
ArrayList类有一个类型参数用来指示元素的类型:
ArrayList<String> files = new ArrayList<String>();这使得代码具有更好的可读性.
注释:前面已经提到,在Java SE7及以后的版本中,构造函数可以省略泛型类型:
ArrayList<String> files = new ArrayList<>();省略的类型可以从变量的类型推断得出.
编译器也可以很好地利用这个信息.当调用get的时候,不需要进行强制类型转换,编译器就知道返回类型为String,而不是Object:
String filename = files.get(0);编译器还知道ArrayList<String>中的add方法有一个类型为String的参数,这将比使用Object类型的参数安全一些.现在,编译器可以进行检查,避免插入错误类型的对象.例如:
files.add(new File("...")); // can only add String object to ArrayList<String>是无法通过编译的.出现编译错误比类在运行时出现类的强制类型转换异常要好得多.类型参数的魅力在于:使得程序具有更好的可读性和安全性.
那些原本涉及许多来自自通用类型(如Object或Comparable接口)的强制类型转换的代码一定会因使用类型参数而受益.
12.2 定义简单泛型类
一个泛型类(generic class)就是具有一个或多个类型变量的类.下面是Pair类的代码:public class Pair<T> { private T first; private T second; public Pair(){ first = null; second = null;} public Pair(T first, T second) { this.first = first; this.second = second; } public T getFirst() { return first; } public T getSecond() { return second; } public void setFirst(T newValue) { first = newValue; } public void setSecond(T newValue) { second = newValue; } }Pair类引入了一个类型变量T,用尖括号<>括起来,并放在类名的后面.泛型类可以有多个类型变量.例如,可以定义Pair类,其中第一个域和第二个域使用不同的类型:
public class Pair<T, U> { ... }类定义中的类型变量指定方法的返回类型以及域和局部变量的类型.例如:
private T first; // uses the type variable注释:类型变量使用大写形式,且比较短,这是很常见的.在Java库中,使用变量E表示集合的元素类型,K和V分别表示表的关键字与值的类型. T(需要时还可以用临近的字母U和S)表示"任意类型".
用具体的类型替换类型变量就可以实例化泛型类型,例如:
Pair<String>可以将结果想象成带有构造器的普通类:
Pair<String>() Pair<String>(String, String)和方法:
String getFirst() String getSecond() void setFirst(String) void setSecond(String)换句话说,泛型类可以看做普通类的工厂.
程序12-1使用了Pair类.静态的minmax方法遍历了数组并同时计算出最小值和最大值.它用一个Pair对象返回了两个结果.
注释:从表面上看,Java的泛型类类似于C++的模板类.唯一明显的不同是Java没有专用的 template 关键字.但是,在本章中将看到,这两种机制有着本质的区别.
pair1/PairTest1.java如下所示:
package pair1; public class PairTest1 { public static void main(String[] args) { String[] words = {"Mary", "had", "a", "little", "lamb"}; Pair<String> mm = ArrayAlg.minmax(words); System.out.println("min = " + mm.getFirst()); System.out.println("max = " + mm.getSecond()); } } class ArrayAlg { /** * Gets the minimum and maximum of an array of strings * @param a an array of strings * @return a pair with the min and max value, or null if a is null or empty */ public static Pair<String> minmax(String[] a) { if (a == null || a.length == 0) return null; String min = a[0]; String max = a[0]; for (int i = 1; i < a.length; i++) { if (min.compareTo(a[i]) > 0) min = a[i]; if (max.compareTo(a[i]) < 0) max = a[i]; } return new Pair<>(min, max); } }运行结果如下所示:
相关文章推荐
- JAVA 内部静态类--解析静态内部类的使用目的与限制
- Java程序初始化顺序
- struts2数据校验方法
- 解决java compiler level does not match the version of the installed java project facet
- spring中注解注入的实现(转)
- Java Base64加密解码实例
- 静态资源[org.springframework.web.servlet.PageNotFound]
- javaMail使用imap协议接收邮件
- JavaWriter源码分析
- JSON数据交互(SpringMVC进行json交互)
- mac 系统上使用eclipse 测试找不到真机设备
- java判断时间大小
- Spring3.2.0之后各个版本完整包下载地址
- spring 3.0 maven pom
- SpringMVC+ajaxFileUpload 异步上传
- java Relative Path and absolute
- Java中关于OOM的场景及解决方法
- Java中public static void main(String args [])的作用
- STRING公共方法
- java根据汉字获取拼音的方法