Confidential 2013 iSoftStone Holdings Limited.All Rights Reserved.,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,Confidential 2013 iSoftStone Holdings Limited.All Rights Reserved.,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2007 iSoftStone Holdings Ltd.All Rights Reserved.,*,Confidential 2013 iSoftStone Holdings Limited.All Rights Reserved.,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,2007 iSoftStone Holdings Ltd.All Rights Reserved.,*,泛型,(Generics),本章名目,强类型集合类,泛型类,泛型通配符,泛型方法,继承中的泛型,泛型接口和枚举,类型去除,集合类中的数据类型,集合类中可以存储各种数据,数据一旦存入,其类型均会转化为Object类型。,从集合类中取出数据时,一般均需要将Object类型转换回存入之前的实际类型,Vector v=new Vector;,v.add(“张三“);/存入字符串,String name=(String)v.get(0);/强制类型转换,OK,v.add(new Date);/存入当前时间对象,OK,/*,由于Date类型不能转换为String,下面语句会在运行时发生错误,但这种错误在编译时不会被检查出来,*/,String date=(String)v.get(1);/编译器不会觉察这里有问题,强类型集合,传统的集合类的实例中可以存储任意类型数据,这种集合类称为弱类型集合类。,JDK1.5以后,引入了强类型集合类,强类型集合类中,只能存储指定类型的数据,在强类型集合类中取出数据时,无需进展类型转换处理,假设数据类型不配备,编译时会直接报错,强类型集合并没有引入新的类名,只需在定义原有集合对象时,用尖括号()指明其存储的数据类型名称即可。,强类型集合例如,/下面的向量类的实例中只能存储字符串类型数据,Vector v=new Vector;,v.add(“张三“);/参与的是字符串,OK,String name=v.get(0);/取出时,无需做类型转换,/*,假设想在这种强类型集合中参与日期数据,在编译时就会报告错误,*/,v.add(new Date);/编译器会直接报告类型不匹配错误,定义泛型,(Generics),类,强类型集合承受了JDK1.5引入的泛型语法。,泛型相当于类中一种特殊的类型,这种类型的特点是在实例化该类时可指定为某个具体的实际类型。,声明包含泛型的类的格式如下:,访问修饰符 class/interface 类名,泛型1 泛型成员1;,泛型2 泛型成员2;,/.,声明中的泛型1、泛型2等等泛型符号可以是任意合法的Java标识符。,泛型类的声明例如,/*,此处声明白一个包含泛型T的泛型类,T代表全部可能的类型,而T,的实际类型在Generic类实例化时指定。,*/,public class Generic,private T f;/f为泛型成员,public void setF(T f)/setF方法的参数类型为泛型T,this.f=f;,public T getF/getF方法的返回类型为泛型T,return f;,/f1中的泛型T在此指定为Boolean类型,Generic f1=new Generic;,/f2中的泛型T在此指定为Integer类型,Generic f2=new Generic;,/f1的setF方法只能承受Boolean类型数据,f1.setF(new Boolean(true);,Boolean b=f1.getF;,System.out.println(b);,/f2的setF方法只能承受Integer类型的数据,f2.setF(new Integer(10);,Integer i=f2.getF;,System.out.println(i);,泛型类,的实例化,创立泛型类的实例时,可以使用一对尖括号指定泛型的真正类型,泛型类实例化时,并不愿定要指明泛型对应的实际类型,此时会使用Object作为泛型的默认类型,编译时编译器会发出警告:,Generic f3=new Generic;,f3.setF(new Boolean(false);,Note:Generic.java uses unchecked or unsafe operations.,Note:Recompile with-Xlint:unchecked for details.,实例化时的泛型的默认类型,建立类型为泛型类的数组,假设要建立泛型类的数组,需要留意new关键字后面不要参与泛型的实际类型名,如下所示:,Generic gs;/声明泛型类的数组,/先对泛型数组进展初始化,gs=new Generic5;/不要写成new Generic5,/再分别为每一个数组元素进展初始化,gs0=new Generic;/为第一个数组元素赋值,/.,public class Generic2,private T1 f1;,private T2 f2;,/.,/给出泛型T1,T2的实际类型,Generic f=,new Generic;,/没有给出T1,T2的实际类型,Generic f1=new Generic;/T1,T2将被默认为是Object类型,包含多个泛型的类定义例如,包含有两个泛型定义的类声明和实例化:,public class Generic3,private T array;/此处不能用new T实例化array,public void setArray(T array),this.array=array;,public T getArray,return array;,泛型成员的使用,在泛型类中的泛型成员不能直接实例化,其实例必需要通过方法的参数传递给泛型成员:,泛型成员实例化例如,通过方法的泛型参数,将数组的实例传递给类中的泛型数组:,String strs=“caterpillar“,“momor“,“bush“;,Generic3 f=new Generic3;,/向泛型成员array传递实际的字符串数组,f.setArray(strs);,/读取泛型成员array的值,将其赋给字符串数组变量strs,strs=f.getArray;/此时array的类型为字符串数组,泛型,成员的可用方法,由于泛型类型只有在类实例化后才能确定,类中的泛型成员只能使用,Object,类型中的方法:,class Generic,T f;,void setF(T f)this.f=f;,/.,void doSome,/*,getClass和toString都是Object中的方法,*/,System.out.println(f.getClass.getName);,System.out.println(f.toString);,extends关键字用来指定泛型的上限,在实例化泛型类时,为该泛型指定的实际类型必需是指定类的子类或指定接口的子接口,在限定泛型的类型时,无论要限定的是接口或是类,都要使用extends关键词,import java.util.List;,public class ListGeneric,private T list;,public void setList(T list),this.list=list;,public T getList,return list;,限制泛型上限类型,ListGeneric f1=,new ListGeneric;,ListGeneric f2=,new ListGeneric;,限制泛型上限类型的例如,/假设不是List的类型,编译时就会发生错误,ListGeneric f3=,new ListGeneric;,type parameter java.util.HashMap is not within its bound,ListGeneric f3=new ListGeneric;,public class Generic,/.,public class Generic,/.,默认的泛型限制类型,定义泛型类别时,假设只写以下代码:,相当于下面的定义方式,限定泛型上限后的成员可用方法,泛型类型的上限一经限定,类中的泛型成员就可使用上限类型中的方法和其他可用成员:,import java.util.List;,import static java.lang.System.out;/静态导入,public class ListGeneric,private T list;,public void setList(T list),this.list=list;,public void doSome,/add、get方法都是List接口中定义的方法,list.add(new Integer(0);,out.println(list.get(0);/此处省略了System,Generic f1=new Generic;,Generic f2=new Generic;,f1=f2;/发生编译错误,incompatible types,found:Generic,required:Generic,f1=f2;,泛型类实例之间的赋值,同一泛型类,假照实例化时给定的实际类型不同,则这些实例的类型是不兼容的,不能相互赋值。,泛型中的,Object,类型兼容性,Object是全部类的父类,因此,全部的类型的实例都可赋值给声明为Object类型的变量,在实例化泛型类时,将泛型指定为Object类型却不存在着和其他类型之间的兼容性:,Generic f1=new Generic;,Generic f2=new Generic;,Generic f=f1;/f1和f类型并不兼容,发生编译错误,f=f2;/f2和f类型同样不兼容,也会发生编译错误,Boolean f1=new Boolean(true);,Integer f2=new Integer(1);,Object f=f1;/,OK,f=f2;/OK,泛型通配字符Wildcard,泛型类实例之间的不兼容性会带来使用的不便。,使用泛型通配符,(?),声明泛型类的变量可以解决这个问题,Generic f1=new Generic;,Generic f2=new Generic;,Generic f3=new Generic;,/f可代表Generic全部可能的实例,Generic f;,f=f1;/OK,f=f2;/OK,f=f3;/OK,通配符用作方法的参数,class Util,/Collection,可以匹配任何强类型集合,static void printCollection(Collection c),for(Object o:c),System.out.println(o);,通配符也可以用于方法的参数类型的声明,表示该参数可承受对应泛型类型的任意实例。,以下类定义中的printCollection方法可以打印任意强类型集合中的内容,Generic f=null;,f=new Generic;/Ok,.,f=new Generic;/OK,.,/以下语句会发生编译错误,由于HashMap没有实现List接口,f=new Genric;,为通配符指定匹配上限,和限制泛型的上限相像,同样可以使用extends关键字限定通配符匹配类型的上限:,incompatible