6.6 泛型
6.6.1 泛型概述
泛型是程序设计语言的种特性。它允许程序员在使用强类型程序设计语言编写代码时定义一些可变部分,这些可变部分在运行前必须做出指明。在编程中用泛型来代替某个实际的类型,而后通过实际调用时传人或推导的类型来对泛型进行替换,以达到代码复用的目的。在使用泛型的过程中,操作的数据类型被指定为一个 参数,这种参数类型在类、接口和方法中,分别称为泛型类、泛型接口、泛型方法。相对于传统上的形参,泛型可以使参数具有更多类型上的变化,使代码能更好地复用。例如下面这段代码:
public class Box {
private string value;
public voidset (String value) {
thig,value = value;
}
public String get (){
ireturn value ;
}
}
上述代码中,定义了一个Box类,Box类中设置了一个String类现的数据。这时程序运行起来是没有问题的。但是,如果需要个能设置 Integer类型数据的类,这个时候只能重新创建个类, 把value改为Integer类型的。可是,随着业务不断增加,需要设置越来越多数据类型的类,这样会使I程变得越来越“笨重” ,并且安全性和重用性都非常低。
泛型就能够很好的解决上述问题,下面使用泛型改造Box类,具体代码如下:
public class Box<T> {
private T t;
public void set (T t) {
this.t=t;
}
public T get (){
return t;
}
}
上述代码中,Box 类在定义时使用了“<T>” 的形式,T表示此类型是由外部调用本类时指定的。这样,在实例化类对象时可以传人除基础数据类型以外的任意类型数据,使类具有良好的通用性。
在泛型中,T可以使用任意的字母代替,如“<A>”“<B>”。 之所以使用“<T>”是因为T是type的缩写,表示类型。
6.6.2 泛型类与泛型对象
泛型类就是在类声明时通过一个标识表示类中某 个属性的类型或者是某个方法的返回值和参数类型。只有用户使用该类的时候,该类所属的类型才能明确。
泛型类的声明格式具体如下:
[访问权限] class 类名称<泛型类型标识1,泛型类型标识2, ..泛型类型标识n>
[访问权限]泛型类型标识 变量名称;
[访问权限]泛型类型标识 方法名称;
[访向权限]返回值类型声明 方法名称 (泛型类型标识变量名称) {};
定义好泛型类之后,就可以创建泛型对象。
创建泛型对象的语法格式具体如下:
类名称<参数化类型>对象名称= new类名称<参数化类型> () ;
为了让读者更好地理解泛型类以及泛型对象的使用,下面先看一个例子,具体如文件6 -22所示。
文件6-22 Example22.java
import java.util.*;
public class Example22 {
public static void main (String[] args){
ArrayList list = new ArrayList () ; //创建ArrayList集合
list .add ("String") ; //添加字符串对象
list.add (2) ;
list.add (1) ; // 添加Integer对象
for (object obj : list) { //遍历集合
String str = (String) obj; //强制转换成String类型
}
}
}
在文件6- 22中,向List集合存入了3个元素,分别是一个字符串 和两个int类型的整数。在取出这些元素时,都将它们强制转换为String类型,由于Integer 对象无法转换为String类型,因此程序在运行时会出现图6- 30所示的错误。
下面对文件6-22中的第4行代码进行修改,如下所示
ArrayList<Integer> list = new ArrayList<Integer>
上面这种写法就限定了ArayList集合只能存储Integer 类型元素,改写后的程序在编译时会出现错误提示,如图6-31所示。
在图6-31中,程序编译报错的原因是修改后的代码限定了集合元素的数据类型,AmyList<Integer>这样的集合只能存储hme类型的元素,程序在编译时,编译器检查出String类型的元素与List集合的规定类型不匹配,编译不通过。
使用泛型可以很好的解决以上问题。下面使用泛型再次对文件6-22进行改写,如文件6-23所示
文件6-23 Example23.java
import java.util.*;
public class Example23{
public static void main (StringI] args) {
ArrayList<Integer> list = new ArrayList<Integer> () ;
list.add (1) ; //添加字符串对象
list.add (2) ;
for (Integer str ; list) { //遍历集合
System.out.printin (str) ;
}
}
}
在文件6- 23中,使用泛型规定了ArayList 集合只能存人Integer类型元素,然后向集合中存人了两个Integer类型元素,并对这个集合进行遍历,从图6-32所示的运行结果可以看出,该文件已经可以正常运行。需要注意的是,在使用泛型后,每次遍历集合元素时,可以指定元素类型为Integer,而不是Object,这样就避免了在程序中进行强制类型转换。