《Java程序设计-8-范型、枚举和内部类.ppt》由会员分享,可在线阅读,更多相关《Java程序设计-8-范型、枚举和内部类.ppt(22页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、JavaJava程序设计程序设计第八章第八章 泛型、枚举和内部类泛型、枚举和内部类学习目标学习目标理解泛型的作用,掌握泛型类的声明及实例化的理解泛型的作用,掌握泛型类的声明及实例化的方法方法掌握枚举类的定义和使用掌握枚举类的定义和使用掌握内部类的定义和使用方法掌握内部类的定义和使用方法掌握匿名类的使用方法掌握匿名类的使用方法8.1泛型什么是泛型什么是泛型u泛型也被称为参数化类型(parameterized type),就是在定义类、接口和方法时,规定了创建将要处理的对象类型。声明泛型类声明泛型类u要求,一个实现先进先出的循环队列。u怎么实现这样的数据结构?u要处理的队列元素类型是什么?实现策略
2、一:非泛型的方法实现策略一:非泛型的方法/程序8-1:一个实现了先进先出的循环队列public class Pool private Object objArray;/记录当前数组中第一个元素出现的位置 private int headLoc /记录当前数组中最后一次插入元素位置 private int tailLoc;public Pool(int length)objArray=new Objectlength;headLoc=-1;/默认在第一个元素之前 tailLoc=-1;/默认在第一个元素之前/从数组中取得一个元素,如果没有返回nullpublic Object get()Obje
3、ct result=null;int idx=(headLoc+1)%objArray.length;/指针后移一位if(objArrayidx!=null)result=objArrayidx;objArrayidx=null;headLoc+;/更新队列头的位置return result;实现策略二:泛型的方法实现策略二:泛型的方法/*程序8-2:一个利用泛型实现了先进先出的循环队列,T是未知类型*/public class GenericPool private Object objArray;private int headLoc;/记录第一个元素出现的位置private int ta
4、ilLoc;/记录最后一次插入元素位置public GenericPool(int length)objArray=new Object10;headLoc=-1;/默认在第一个元素之前tailLoc=-1;/默认在第一个元素之前/*从数组中取得一个元素,如果没有返回null,方法的返回值类型为T,这里和类的未知参数一致*/public T get()Object result=null;int idx=(headLoc+1)%objArray.length;/指针后移一位if(objArrayidx!=null)result=objArrayidx;objArrayidx=null;head
5、Loc+;return(T)result;8.1.2声明泛型接口声明声明public interface IPool T get();int add(T t);实现实现public class GenericPool implements IPool public class GenericPool implements IPool 8.1.3声明泛型方法泛型方法泛型方法u除了泛型类和接口外,还可以只单独定义一个方法作为泛型方法,可以指定方法参数或者返回值指定为泛型类型的声明,留待运行时确定u泛型方法就可以声明在泛型类中,也可以声明在普通类中。public class ArrayTool pu
6、blic static void insert(E e,int idx)/请自己添加代码public static E valueAt(E e)/请自己添加代码 8.1.4泛型参数的限定定义泛型参数的上界定义泛型参数的上界public class NumberGenericPool说明说明u上述方式的声明规定了NumberGenericPool类所能处理的参数其类型和Number有继承关系uextends关键字所声明的上界既可以是一个类,也可以是一个接口u当泛型参数这样声明时,在实例化一个泛型类时,需要明确类型必须为指定上界类型或者子类。NumberGenericPool pool=new N
7、umberGenericPool(2);8.1.4泛型参数的限定定义参数的下界定义参数的下界List cards=new ArrayList();说明说明u通过使用super关键字可以固定泛型参数的类型为某种类型或者其超类u当程序希望为一个方法的参数限定类型时,通常可以使用下限通配符public static void sort(T a,Comparator c)通配符通配符u“?”符号表明参数的类型可以是任何一种类型,他和参数T的含义是有区别的。T表示一种未知类型,而“?”表示任何一种类型。这种通配符一般有以下三种用法:u单独的?,用于表示任何类型。u?extends type,表示带有上界
8、。u?super type,表示带有下界。8.2枚举如果我们想定义一个成绩类,成绩的范围只能如果我们想定义一个成绩类,成绩的范围只能是是A A、B B、C C、D D、E E,接受其它类型的值都是违,接受其它类型的值都是违法的,应该如何定义呢?我们可以定义一个成法的,应该如何定义呢?我们可以定义一个成绩类,但如何表示成绩呢,整型、字符型?似绩类,但如何表示成绩呢,整型、字符型?似乎都不合适,因为没有明确的类型对应,即使乎都不合适,因为没有明确的类型对应,即使是字符型,那么超出了是字符型,那么超出了AA、B B、C C、D D、EE范围范围的字符程序需要特别处理,以便保证应用安全。的字符程序需要
9、特别处理,以便保证应用安全。JavaJava语言提供了一种称为枚举的类型定义方法语言提供了一种称为枚举的类型定义方法.1 1 声明枚举类声明枚举类 upublic enum Grade A,u B,u C,u D,u Eu;它包括一个关键字它包括一个关键字enumenum,一个新枚举类型的名,一个新枚举类型的名字字 GradeGrade以及为以及为GradeGrade定义的一组值,这里的值定义的一组值,这里的值既非整型,亦非字符型。既非整型,亦非字符型。枚举类枚举类u枚举类是一个类,它的隐含父类是。u枚举值并不是整数或其它类型,是被声明的枚举类的自身实例,例如A是Grade的一个实例。u枚举类
10、不能有public修饰的构造函数,构造函数都是隐含private,编译器自动处理。u每个枚举值隐含都是由public、static、final修饰的,无须自己添加这些修饰符。u枚举值可以用=或 equals()进行彼此相等比较。一个枚举的例子一个枚举的例子第一个类文件第一个类文件Grade.javaGrade.javapublic enum Grade public enum Grade A,A,B,B,C,C,D,D,E E 第二个类文件第二个类文件AcademicRecord.javaAcademicRecord.java第三个类文件第三个类文件Student.java Student.j
11、ava 3 3 使用使用switchswitch判断判断switch(student.getGrade()case A:break;case B:break;case C:break;case D:break;case E:break;4.4.为枚举类增加构造函数为枚举类增加构造函数enum Size Small(0.8),/Small的类型为Size,而Size有指定的构造函数 Medium(1.0),Large(1.2);/分号表示枚举值定义结束private double pricingFactor;/构造函数,如Small(0.8),pricingFactor=0.8Size(doub
12、le p)pricingFactor=p;public double getPricingFactor()return pricingFactor;8.3内部类内部类的声明和应用内部类的声明和应用u内部类的使用通常出现在一个类只为另一个类提供单独的服务。/程序8-3:一个内部类的定义public class OuterClass private String name;private String state;public OuterClass(String name,String state)super();this.name=name;this.state=state;private vo
13、id say()System.out.println(外部:+name+的状态是+state);public class InnerClass public void alarm()System.out.println(内部:+name+的状态是+state);say();由于内部类存在于外部类内,因此他了解外部类由于内部类存在于外部类内,因此他了解外部类的一切构成细节,因此,可以根据需要使用外部的一切构成细节,因此,可以根据需要使用外部类的属性、方法,即使他们可能是用类的属性、方法,即使他们可能是用privateprivate修修饰的。饰的。/程序8-3:一个内部类的定义public cla
14、ss OuterClass 。public static void main(String args)OuterClass outer=new OuterClass(冰箱,完好);OuterClass.InnerClass inner=outer.new InnerClass();inner.alarm();使用内部类的一些用法使用内部类的一些用法u内部类在作用上如同一个类定义的属性一样,但差异在于内部类同样可以在外部类中直接作为类型出现,用于声明外部类的属性类型,方法的参数或返回值类型。u由于InnerClass是OuterClass的内部类,因此,在需要创建一个InnerClass的实例时
15、,需要通过一个OuterClass的实例来创建,如上面的语句中在new运算符前添加了outer实例名,当然如果在OuterClass内的方法中创建InnerClass的实例时,是不需要这个前缀的。u有了一个内部类实例,通过使用变量名可以引用可用的方法和属性8.3.2具有static修饰的内部类public class OuterClass2 private String name;private String state;public OuterClass2(String name,String state)super();this.name=name;this.state=state;pri
16、vate void say()System.out.println(外部:+name+的状态是+state);static class InnerClass public void alarm()System.out.println(static内部类无法使用OuterClass+的非static修饰的属性和方法);OuterClass.InnerClass inner=new OuterClass.InnerClass();8.3.3局部内部类局部内部类局部内部类u一个内部类可以被声明在一个方法内部,这样的类被称为局部内部类。u局部内部类不能被声明为public、protected和priv
17、ate,只能被abstract和final来修饰,他可以引用外部类的属性和方法,但只能引用包含它的方法中final类型的局部变量。8.3.4匿名内部类顾名思义,匿名内部类就是没有名字的类。顾名思义,匿名内部类就是没有名字的类。u例如:Arrays.sort()方法,其方法要求一个是个比较器类型的对象。Arrays.sort(accounts,new Comparator()Overridepublic int compare(Account o1,Account o2)int result=0;if(o1.getBalance()o2.getBalance()result=1;else if(o1.getBalance()=o2.getBalance()result=0;else result=-1;return result;);