1、本章内容本章内容l第一节 抽象类l第二节 接 口l第三节 内部类l第四节 枚 举l第五节 注 解第一节 抽象类 抽象类抽象类(abstract class)l随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。抽象类抽象类l用abstract关键字来修饰一个类时,这个类叫做抽象类;l 用abstract来修饰一个方法时,该方法叫做抽象方法。抽象方法:只有方法的声明,没有方法的实现。以分号结束:abstract int abstractMethod(int a
2、);l含有抽象方法的类必须被声明为抽象类。l抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类。l不能用abstract修饰属性、私有方法、构造器、静态方法、final的方法。抽象类举例抽象类举例abstract class A abstract void m1();public void m2()System.out.println(A类中定义的m2方法);class B extends A void m1()System.out.println(B类中定义的m1方法);public class Test publ
3、ic static void main(String args )A a=new B();a.m1();a.m2();抽象类应用抽象类应用在航运公司系统中,Vehicle类需要定义两个方法分别计算运输工具的燃料效率和行驶距离。抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类。问题:卡车(Truck)和驳船(RiverBarge)的燃料效率和行驶距离的计算方法完全不同。Vehicle类不能提供计算方法,但子类可以。l解决方案解决方案Java允许类设计者指定:超类声明一个方法但不提供实现,该方法的实现由子允许类设计者指定:超类声明一个方法但不提供实现,该方法的实现由子
4、类提供。这样的方法称为类提供。这样的方法称为抽象方法抽象方法。有一个或更多抽象方法的类称为。有一个或更多抽象方法的类称为抽象类抽象类。lVehicle是一个抽象类,有两个抽象方法。是一个抽象类,有两个抽象方法。public abstract class Vehiclepublic abstract double calcFuelEfficiency();/计算燃料效率的抽象方法public abstract double calcTripDistance();/计算行驶距离的抽象方法public class Truck extends Vehiclepublic double calcFuel
5、Efficiency()/写出计算卡车的燃料效率的具体方法 public double calcTripDistance()/写出计算卡车行驶距离的具体方法 public class RiverBarge extends Vehicle public double calcFuelEfficiency()/写出计算驳船的燃料效率的具体方法 public double calcTripDistance()/写出计算驳船行驶距离的具体方法抽象类应用抽象类应用注意:抽象类不能实例化 new Vihicle()是非法的思思 考考问题1:为什么抽象类不可以使用final关键字声明?问题2:一个抽象类中可
6、以定义构造器吗?1.将Frock类声明为抽象类,在类中声明抽象方法calcArea方法,用来计算衣服的布料面积。2.通过编写代码来验证抽象类中是否可包含属性、具体方法和构造器。3.编写Shirt类继承Frock类,实现 calcArea方法,用来计算衬衣所需的布料面积(尺寸*1.3)。4.在TestShirt类的main方法中:1.试着创建Frock对象,确认是否允许?2.使用本态引用创建Shirt对象,并调用calcArea方法,打印计算结果。3.使用Frock 多态引用创建Shirt对象,并调用calcArea方法,打印计算结果。练练 习习作作 业业编写一个Employee类,声明为抽象类
7、,包含如下三个属性:name,id,salary。提供必要的构造器和抽象方法:work()。对于Manager类来说,他既是员工,还具有奖金(bonus)的属性。请使用继承的思想,设计CommonEmployee类和Manager类,要求类中提供必要的方法进行属性访问。模板方法设计模式模板方法设计模式(TemplateMethod)抽象类体现的就是一种模板模式的设计,抽象类作为抽象类作为多个子类的通用模板多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式。解决解决的问题的问题:当功能内部一部分实现是确定,一部分实现是不确定的。这时可以把不确定的部分暴露出
8、去,让子类去实现。编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,就是一种模板模式。模板方法设计模式模板方法设计模式(TemplateMethod)abstract class Templatepublic final void getTime()long start=System.currentTimeMillis();code();long end=System.currentTimeMillis();System.out.println(执行时间是:+(end-start);public abstract void code();class SubTem
9、plate extends Templatepublic void code()for(int i=0;i10000;i+)System.out.println(i);第二节 接 口 接接 口口(1)l有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。l接口(interface)是抽象方法和常量值的定义的集合。l从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。l实现接口类:class SubClass implements InterfaceA l一个类可以实现多个接口,
10、接口也可以继承其它接口。接接 口口(2)运动员运动员(抽象类)(抽象类)学生学生(抽象类)(抽象类)篮球运篮球运动员动员大学生大学生跨栏运跨栏运动员动员中学生中学生学习英语学习英语的技能的技能(接口)(接口)接接 口口(3)l接口的特点:接口的特点:用interface来定义。接口中的所有成员变量都默认是由public static final修饰的。接口中的所有方法都默认是由public abstract修饰的。接口没有构造器。接口采用多继承机制。l接口定义举例 public interface Runner int ID=1;void start();public void run();v
11、oid stop();public interface Runner public static final int ID=1;public abstract void start();public abstract void run();public abstract void stop();接接 口口(4)l实现接口的类中必须提供接口中所有方法的具体实现内容,方可实例化。否则,仍为抽象类。l接口的主要用途就是被实现类实现。(面向接口编程)l与继承关系类似,接口与实现类之间存在多态性l定义Java类的语法格式:先写extends,后写implements class extends impl
12、ements ,*接口应用举例接口应用举例(1)Runner+start()+run()+stop()Person+start()+run()+stop()+dance()Car+start()+run()+stop()+fillFuel()+crack()Bird+start()+run()+stop()+fly()接口应用举例接口应用举例(1)public interface Runner public void start();public void run();public void stop();public class Person implements Runner public
13、 void start()/准备工作:弯腰、蹬腿、咬牙、瞪眼/开跑public void run()/摆动手臂/维持直线方向public void stop()/减速直至停止、喝水。接接口口应应用用举举例例(2)l 一个类可以实现多个无关的接口interface Runner public void run();interface Swimmer public double swim();class Creatorpublic int eat()class Man extends Creator implements Runner,Swimmerpublic void run()public
14、double swim()public int eat()l与继承关系类似,接口与实现类之间存在多态性与继承关系类似,接口与实现类之间存在多态性public class Testpublic static void main(String args)Test t=new Test();Man m=new Man();t.m1(m);t.m2(m);t.m3(m);public String m1(Runner f)f.run();public void m2(Swimmer s)s.swim();public void m3(Creator a)a.eat();接口的其他问题接口的其他问题l如
15、果实现接口的类中没有实现接口中的全部方法,必须将此类定义为抽象类 l接口也可以继承另一个接口,使用extends关键字。linterface MyInterfaceString s=“MyInterface”;public void absM1();interface SubInterface extends MyInterfacepublic void absM2();public class SubAdapter implements SubInterfacepublic void absM1()System.out.println(“absM1”);public void absM2()
16、System.out.println(“absM2”);实现类SubAdapter必须给出接口SubInterface以及父接口MyInterface中所有方法的实现。工厂方法工厂方法(FactoryMethod)概述概述:定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。适用性:适用性:1.当一个类不知道它所必须创建的对象的类的时候2.当一个类希望由它的子类来指定它所创建的对象的时候 3.当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候工厂方法举例工厂方法举例工厂方法工厂方法(
17、FactoryMethod)总结:总结:FactoryMethod模式是设计模式中应用最为广泛的模式,在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要。FactoryMethod解决的就是这个问题,它通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,较好的解决了这种紧耦合的关系。代理模式代理模式(Proxy)概述:概述:为其他对象提供一种代理以控制对这个对象的访问。interface Objectvoid action();class ProxyObject implements ObjectObject obj;public void
18、 action()System.out.println(代理开始);obj.action();System.out.println(代理结束);public ProxyObject()System.out.println(这是代理类);obj=new ObjectImpl();class ObjectImpl implements Objectpublic void action()System.out.println(=);System.out.println(=);System.out.println(被代理的类);System.out.println(=);System.out.prin
19、tln(=);public class Test2 public static void main(String args)Object ob=new ProxyObject();ob.action();接口用法总结接口用法总结l通过接口可以实现不相关类的相同行为,而不需要考虑这些类之间的层次关系。l通过接口可以指明多个类需要实现的方法,一般用于定义对象的扩张功能。l接口主要用来定义规范。解除耦合关系。接口和抽象类之间的关系接口和抽象类之间的关系在开发中,一个类不要去继承一个已经实现好的类,要么继承抽象类,要么实现接口。No.区别点区别点抽象类抽象类接口接口1定义包含一个抽象方法的类抽象方法和
20、全局常量的集合2组成构造方法、抽象方法、普通方法、常量、变量常量、抽象方法3使用子类继承抽象类(extends)子类实现接口(implements)4关系抽象类可以实现多个接口接口不能继承抽象类,但允许继承多个接口5常见设计模式模板设计工厂设计、代理设计6对象都通过对象的多态性产生实例化对象7局限抽象类有单继承的局限接口没有此局限8实际作为一个模板是作为一个标准或是表示一种能力9选择如果抽象类和接口都可以使用的话,优先使用接口,因为避免单继承的局限10特殊一个抽象类中可以包含多个接口,一个接口中可以包含多个抽象类练练 习习1.声明Clothing接口,在接口中声明 calcArea方法、get
21、Color方法和getDetails方法。2.改写Shirt类实现Clothing接口,然后实现接口中的所有方法。3.在TestShirt类的main方法中:试着创建 Clothing对象,确认是否允许?使用本态引用创建Shirt对象,并调用calcArea方法,打印计算结果。使用Clothing多态引用创建Shirt对象,并调用calcArea方法,打印计算结果。作作 业业l定义一个接口用来实现两个对象的比较。定义一个接口用来实现两个对象的比较。interface CompareObjectpublic int compareTo(Object o);/若若返返回回值值是是 0,代代表表相相
22、等等;若若为为正正数数,代表当前对象大;负数代表当前对象小代表当前对象大;负数代表当前对象小 l定义一个定义一个Circle类。类。l定定义义一一个个ComparableCircle类类,继继承承Circle类类并并且且实实现现CompareObject接接口口。在在ComparableCircle类类中中给给出出接接口口中中方方法法compareTo的的实实现现体体,用用来来比比较较两两个圆的半径大小。个圆的半径大小。l定定义义一一个个测测试试类类TestInterface,创创建建两两个个ComparableCircle对对象象,调调用用compareTo方法比较两个方法比较两个类类的半径
23、大小。的半径大小。l思思考考:参参照照上上述述做做法法定定义义矩矩形形类类Rectangle和和ComparableRectangle类类,在在ComparableRectangle类类中中给给出出compareTo方方法法的的实实现现,比比较较两两个个矩矩形形的的面面积大小。积大小。接口的应用体会接口的应用体会第三节 内部类 类的成员之五:内部类类的成员之五:内部类l在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。lInner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。Inner class的名字不能与包含它的类名相同;lI
24、nner class可以使用外部类的私有数据,因为它是外部类的成员,同一个类的成员之间可相互访问。而外部类要访问内部类中的成员需要:内部类.成员或者内部类对象.成员。l分类:成员内部类分类:成员内部类(static成员内部类和非static成员内部类)局部局部内内部类部类(不谈修饰符)、匿名内部类内部类举例内部类举例(1)class A private int s;public class B public void mb()s=100;System.out.println(在内部类B中s=+s);public void ma()B i=new B();i.mb();public class
25、Test public static void main(String args)A o=new A();o.ma();内部类举例内部类举例(2)public class A private int s=111;public class B private int s=222;public void mb(int s)System.out.println(s);/局部变量s System.out.println(this.s);/内部类对象的属性s System.out.println(A.this.s);/外层类对象属性s public static void main(String arg
26、s)A a=new A();A.B b=a.new B();b.mb(333);内部类特性内部类特性lInner class作为类的成员:作为类的成员:可以声明为final的和外部类不同,Inner class可声明为private或protected;Inner class 可以声明为static的,但此时就不能再使用外层类的非static的成员变量;lInner class作为类:作为类:可以声明为abstract类,因此可以被其它的内部类继承【注意】非static的内部类中的成员不能声明为static的,只有在外部类或static的内部类中才可声明static成员。匿名内部类不能定义任何
27、静态成员、方法和类,只能创建匿名内部类的一个实例。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。new 父类构造器(实参列表)父类构造器(实参列表)|实现接口实现接口()/匿名内部类的类体部分匿名内部类的类体部分AnonymousTest.java匿名内匿名内部类部类interface Apublic abstract void fun1();public class Outerpublic static void main(String args)new Outer().callInner(new A()/接口是不能new但此处比较特殊是子类对象实现接口,只不过没有为
28、对象取名public void fun1()System.out.println(“implement for fun1););/两步写成一步了public void callInner(A a)a.fun1();public class Test public Test()Inner s1=new Inner();s1.a=10;Inner s2=new Inner();s2.a=20;Test.Inner s3=new Test.Inner();System.out.println(s3.a);练练 习习判断输出结果为何?判断输出结果为何?class Inner public int a=
29、5;public static void main(String args)Test t=new Test();Inner r=t.new Inner();System.out.println(r.a);第四节 枚 举枚举类枚举类主要内容主要内容:l如何自定义枚举类如何自定义枚举类l如何使用如何使用enum定义枚举类定义枚举类枚举类的主要方法枚举类的主要方法l实现接口的枚举实现接口的枚举类类枚举类入门枚举类入门lJDK1.5之前需要自定义枚举类lJDK 1.5 新增的 enum 关键字关键字用于定义枚举类枚举类l若枚举只有一个成员,则可以作为一种单例模式的实现方式枚举类的属性枚举类的属性l枚举
30、类对象的属性不应允许被改动枚举类对象的属性不应允许被改动,所以应该使用所以应该使用 private final 修饰修饰枚举类的使用 private final 修饰的属性应该在构造器中为其赋值若枚举类显式的定义了带参数的构造器,则在列出枚举值时也必须对应的传入参数Enum枚举类枚举类l必须在枚举类的第一行声明枚举类对象。必须在枚举类的第一行声明枚举类对象。l枚举类和普通类的区别:使用 enum 定义的枚举类默认继承默认继承了 java.lang.Enum 类枚举类的构造器只能使用 private 访问控制符枚举类的所有实例必须在枚举类中显式列出(,分隔分隔 ;结尾结尾).列出的实例系统会自动
31、添加列出的实例系统会自动添加 public static final 修饰修饰lJDK 1.5 中可以在中可以在 switch 表达式中使用表达式中使用Enum定义的枚定义的枚举类的对象作为表达式举类的对象作为表达式,case 子句可以直接使用枚举值的名字,无需添加枚举类作为限定使用使用 Enum 定义的定义的 SeasonEnum枚举类枚举类l枚举类的主要方法:枚举类的主要方法:values()方法方法:返回枚举类型的对象数组。该方法可以很方便地遍历所有的枚举值。valueOf(String str):可以把一个字符串转为对应的枚举类对象。要求字符串必须是枚举类对象的“名字”。如不是,会有运
32、行时异常。枚举的方法枚举的方法实现接口的枚举类实现接口的枚举类l和普通 Java 类一样,枚举类可以实现一个或多个接口l若需要每个枚举值在调用实现的接口方法呈现出不若需要每个枚举值在调用实现的接口方法呈现出不同的行为方式同的行为方式,则可以让每个枚举值分别来实现该则可以让每个枚举值分别来实现该方法方法练练 习习1.声明Week枚举类,其中包含星期一至星期日的定义;2.在TestWeek类中声明方法中printWeek(Week week),根据参数值打印相应的中文星期字符串。提示,使用switch语句实现。3.在main方法中从命令行接收一个1-7的整数(使用Integer.parseInt方
33、法转换),分别代表星期一至星期日,打印该值对应的枚举值,然后以此枚举值调用printWeek方法,输出中文星期。第五节 注 解注解注解Annotation主要内容主要内容lJDK内置的基本注解类型(3个)l自定义注解类型l对注解进行注解(4个)注解注解(Annotation)概述概述l从 JDK 5.0 开始,Java 增加了对元数据(MetaData)的支持,也就是 Annotation(注解)lAnnotation 其实就是代码里的特殊标记特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理.通过使用 Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入
34、一些补充信息.lAnnotation 可以像修饰符一样被使用,可用于修饰包修饰包,类类,构构造器造器,方法方法,成员变量成员变量,参数参数,局部变量的声明局部变量的声明,这些信息被保存在 Annotation 的“name=value”对中.lAnnotation 能被用来为程序元素(类,方法,成员变量等)设置元数据基本的基本的 Annotationl使用 Annotation 时要在其前面增加 符号,并把该把该 Annotation 当成一个修饰符使用。当成一个修饰符使用。用于修饰它支持的程序元素l三个基本的 Annotation:Override:限定重写父类方法,该注释只能用于方法Dep
35、recated:用于表示某个程序元素(类,方法等)已过时SuppressWarnings:抑制编译器警告自定义自定义 Annotationl定义新的 Annotation 类型使用 interface 关键字lAnnotation 的的成员变量成员变量在在 Annotation 定义中以无参数方法定义中以无参数方法的形式来声明的形式来声明.其方法名和返回值定义了该成员的名字和类其方法名和返回值定义了该成员的名字和类型型.l可以在定义 Annotation 的成员变量时为其指定初始值,指定指定成员变量的初始值可使用成员变量的初始值可使用 default 关键字关键字public interfac
36、e MyAnnotation String name()default“atguigu;l没有成员定义的 Annotation 称为标记;包含成员变量的 Annotation 称为元数据 Annotation提取提取 Annotation 信息信息lJDK 5.0 在 java.lang.reflect 包下新增了 AnnotatedElement 接口接口,该接口代表程序中可以接受注解的程序元素代表程序中可以接受注解的程序元素l当一个当一个 Annotation 类型被定义为运行时类型被定义为运行时 Annotation 后后,该注释才是运行时可见,当 class 文件被载入时保存在 cla
37、ss 文件中的 Annotation 才会被虚拟机读取l程序可以调用 AnnotationElement 对象的如下方法来访问 Annotation 信息JDK 的元的元 AnnotationlJDK 的元 Annotation 用于修饰其他 Annotation 定义lJDK5.0提供了专门在注解上的注解类型,分别是:RetentionTargetDocumentedInherited元数据String name=“atguigu”;JDK 的元的元 AnnotationlRetention:只能用于修饰一个 Annotation 定义,用于指定该 Annotation 可以保留多长时间,R
38、entention 包含一个 RetentionPolicy 类型的成员变量,使用 Rentention 时必须为该 value 成员变量指定值:RetentionPolicy.SOURCE:编译器直接丢弃这种策略的注释RetentionPolicy.CLASS:编译器将把注释记录在 class 文件中.当运行 Java 程序时,JVM 不会保留注解。这是默认值RetentionPolicy.RUNTIME:编译器将把注释记录在编译器将把注释记录在 class 文件文件中中.当运行当运行 Java 程序时程序时,JVM 会保留注释会保留注释.程序可以通过反射程序可以通过反射获取该注释获取该注释
39、public enum RetentionPolicySOURCE,CLASS,RUNTIMERetention(RetentionPolicy.SOURCE)interface MyAnnotation1 interface MyAnnotation2 Retention(RetentionPolicy.RUNTIME)interface MyAnnotation3 JDK 的元的元 AnnotationlTarget:用于修饰 Annotation 定义,用于指定被修饰的 Annotation 能用于修饰哪些程序元素.Target 也包含一个名为 value 的成员变量.lDocument
40、ed:用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档.定义为Documented的注解必须设置Retention值为RUNTIME。lInherited:被它修饰的 Annotation 将具有继承性继承性.如果某个类使用了被 Inherited 修饰的 Annotation,则其子类将自动具有该注解实际应用中,使用较少练练 习习1.编写一个Person类,使用Override注解它的toString方法2.自定义一个名为“MyTiger”的注解类型,它只可以使用在方法上,带一个String类型的value属性,然后在第1题中的Person类上正确使用。