泛型(Generics)Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.本章目录强类型集合类泛型类泛型通配符泛型方法继承中的泛型泛型接口和枚举类型去除Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.集合类中的数据类型•集合类中可以存储各种数据,数据一旦存入,其类型均会转化为Object类型。•从集合类中取出数据时,一般均需要将Object类型转换回存入之前的实际类型Vectorv=newVector();v.add(张三);//存入字符串Stringname=(String)v.get(0);//强制类型转换,OKv.add(newDate());//存入当前时间对象,OK/*由于Date类型不能转换为String,下面语句会在运行时发生错误,但这种错误在编译时不会被检查出来*/Stringdate=(String)v.get(1);//编译器不会发现这里有问题Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.强类型集合•传统的集合类的实例中可以存储任意类型数据,这种集合类称为弱类型集合类。•JDK1.5以后,引入了强类型集合类–强类型集合类中,只能存储指定类型的数据–在强类型集合类中取出数据时,无需进行类型转换处理,如果数据类型不配备,编译时会直接报错–强类型集合并没有引入新的类名,只需在定义原有集合对象时,用尖括号()指明其存储的数据类型名称即可。Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.强类型集合示例//下面的向量类的实例中只能存储字符串类型数据VectorStringv=newVectorString();v.add(张三);//加入的是字符串,OKStringname=v.get(0);//取出时,无需做类型转换/*如果想在这种强类型集合中加入日期数据,在编译时就会报告错误*/v.add(newDate());//编译器会直接报告类型不匹配错误Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.定义泛型(Generics)类•强类型集合采用了JDK1.5引入的泛型语法。•泛型相当于类中一种特殊的类型,这种类型的特点是在实例化该类时可指定为某个具体的实际类型。•声明包含泛型的类的格式如下:[访问修饰符]class/interface类名泛型1,泛型2,…{泛型1泛型成员1;泛型2泛型成员2;//....}•声明中的泛型1、泛型2等等泛型符号可以是任意合法的Java标识符。Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.泛型类的声明示例/*此处声明了一个包含泛型T的泛型类,T代表所有可能的类型,而T的实际类型在Generic类实例化时指定。*/publicclassGenericT{privateTf;//f为泛型成员publicvoidsetF(Tf){//setF方法的参数类型为泛型Tthis.f=f;}publicTgetF(){//getF方法的返回类型为泛型Treturnf;}}Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.//f1中的泛型T在此指定为Boolean类型GenericBooleanf1=newGenericBoolean();//f2中的泛型T在此指定为Integer类型GenericIntegerf2=newGenericInteger();//f1的setF方法只能接受Boolean类型数据f1.setF(newBoolean(true));Booleanb=f1.getF();System.out.println(b);//f2的setF方法只能接受Integer类型的数据f2.setF(newInteger(10));Integeri=f2.getF();System.out.println(i);泛型类的实例化•创建泛型类的实例时,可以使用一对尖括号指定泛型的真正类型Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.•泛型类实例化时,并不一定要指明泛型对应的实际类型,此时会使用Object作为泛型的默认类型•编译时编译器会发出警告:Genericf3=newGeneric();f3.setF(newBoolean(false));Note:Generic.javausesuncheckedorunsafeoperations.Note:Recompilewith-Xlint:uncheckedfordetails.实例化时的泛型的默认类型Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.建立类型为泛型类的数组•如果要建立泛型类的数组,需要注意new关键字后面不要加入泛型的实际类型名,如下所示:GenericString[]gs;//声明泛型类的数组//先对泛型数组进行初始化gs=newGeneric[5];//不要写成newGenericString[5]//再分别为每一个数组元素进行初始化gs[0]=newGenericString();//为第一个数组元素赋值//....Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.publicclassGeneric2T1,T2{privateT1f1;privateT2f2;//....}//给出泛型T1,T2的实际类型GenericInteger,Booleanf=newGenericInteger,Boolean();//没有给出T1,T2的实际类型Genericf1=newGeneric();//T1,T2将被默认为是Object类型包含多个泛型的类定义示例•包含有两个泛型定义的类声明和实例化:Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.publicclassGeneric3T{privateT[]array;//此处不能用newT[]实例化arraypublicvoidsetArray(T[]array){this.array=array;}publicT[]getArray(){returnarray;}}泛型成员的使用•在泛型类中的泛型成员不能直接实例化,其实例必须要通过方法的参数传递给泛型成员:Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.泛型成员实例化示例•通过方法的泛型参数,将数组的实例传递给类中的泛型数组:String[]strs={caterpillar,momor,bush};Generic3Stringf=newGeneric3String();//向泛型成员array传递实际的字符串数组f.setArray(strs);//读取泛型成员array的值,将其赋给字符串数组变量strsstrs=f.getArray();//此时array的类型为字符串数组Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.泛型成员的可用方法•由于泛型类型只有在类实例化后才能确定,类中的泛型成员只能使用Object类型中的方法:classGenericT{Tf;voidsetF(Tf){this.f=f;}//....voiddoSome(){/*getClass和toString都是Object中的方法*/System.out.println(f.getClass().getName());System.out.println(f.toString());}}Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.•extends关键字用来指定泛型的上限,在实例化泛型类时,为该泛型指定的实际类型必须是指定类的子类或指定接口的子接口•在限定泛型的类型时,无论要限定的是接口或是类,都要使用extends关键词importjava.util.List;publicclassListGenericTextendsList{privateTlist;publicvoidsetList(Tlist){this.list=list;}publicTgetList(){returnlist;}}限制泛型上限类型Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.ListGenericVectorf1=newListGenericVector();ListGenericArrayListf2=newListGenericArrayList();限制泛型上限类型的示例//如果不是List的类型,编译时就会发生错误ListGenericHashMapf3=newListGenericHashMap();typeparameterjava.util.HashMapisnotwithinitsboundListGenericHashMapf3=newListGenericHashMap();Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.publicclassGenericT{//....}publicclassGenericTextendsObject{//....}默认的泛型限制类型•定义泛型类别时,如果只写以下代码:•相当于下面的定义方式Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.限定泛型上限后的成员可用方法•泛型类型的上限一经限定,类中的泛型成员就可使用上限类型中的方法和其他可用成员:importjava.util.List;importstaticjava.lang.System.out;//静态导入publicclassListGenericTextendsList{privateTlist;publicvoidsetList(Tlist){this.list=list;}publicvoiddoSome(){//add、get方法都是List接口中定义的方法list.add(newInteger(0));out.println(list.get(0));//此处省略了System}}Confidential©2013iSoftStoneHoldingsLimited.AllRightsReserved.GenericBooleanf1=newGenericBoolean();GenericIntegerf2=newGenericInteger();f1=f2;//发生编译错误incompatibletypesfound:Genericjava.lang.Integerrequired:Genericjava.lang.Booleanf1=f2;泛型类实例之间的赋值•同一泛型类,如果实例化时给定的实际类型不同,则这些实例的类型是不兼容的,不能相互