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