打通经脉java基础入门编程详解_第1页
打通经脉java基础入门编程详解_第2页
打通经脉java基础入门编程详解_第3页
打通经脉java基础入门编程详解_第4页
打通经脉java基础入门编程详解_第5页
已阅读5页,还剩25页未读, 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、接口本章将详细讲述 Java 语言中有关接口的各方面知识,说明接口的定义、特性,以及在接口中定义和使用成员变量与方法的技巧。本章将从语法和具体含义上对比接口与抽象类的不同,讲述基于接口的多态这一重要概念。本章还将深入分析接口与回调的关系,详细说明instanceof 关键字的使用方法,在本章的最后将简本章主要内容:明 Java 语言中的范型。接口的基础概念成员变量在接口中的使用方法在接口中的使用接口和抽象类 基于接口的多态接口与回调instanceof 的使用范型5.1接口概述及其特性Java 语言中的接口是实现组件可性的关键,可组件的关键在于存在一系列公用的,是一些方法特征的集合,一接口,以

2、及每个组件实现了这个接口。接口是一系列方法的个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有截然不同的行为。5.1.1接口概述Java 语言中的接口有两种含义,第一种就是狭义的 Java 接口,表示 Java 语言中存在的一种特定的结构,这一结构有着特定的语法和结构。第二种是泛指类所具有的方法的特征集合,是一种逻辑上的抽象概念。通常情况下,前者叫做“Java 接口”,而后者叫做“接口”。在 Java 语言规范中,一个方法的特征仅仅包括方法的名字、参数的数目和种类,而不包括方法的返回类型、参数的名字,以及所抛出的异常。在 Java 编译器检查方法

3、的重载时,会根据这些条件来判断两个方法是否是重载方法。但在 Java 编译器检查方法的重写时,则会进一步检查两个方法的返回类型和抛出的异常是否相同。实现接口继承的规则是不同的,一个类最多允许有一个直接的超类,但是可以实现多个接口。Java 接口本身没有任何具体的实现逻辑,因为 Java 接口不涉及具体的实现细节,只用于描述接口所具有的公共行为,因此 Java 接口比抽象类更抽象化。此外,Java 接口的方法只能是抽象的和公开的。Java 接口没有任何构造函数,但可以有公共的、静态的和最终的成员变量。Java 接口把方法的特征与方法的实现分割开来,这种分割体现在接口常常代表一个角色,接口包装了与

4、该角色相关的操作和属性,而实现这个接口的类便是扮演这个角色的演员。一个角色可以由不同的演员来演,而不同的演员除了扮演一个共同的角色之外,并不要求有其他的共同之处。跟继承机制类似,Java 接口也是面象技术的一个重要特性。由于 Java 语言本身没有多继承机制,因此接口机制的引入间接地实现了多继承机制。前面的章节已经详细地说明了抽象类这一重要概念,抽象类中包含一个或多个抽象方法,该抽象类的子类必须实现这些抽象方法。 Java 接口类似于抽象类,不同之处在于 Java 接口中的所有方法都是抽象的,由实现这一接口的类来实现具体的细节。在 Java 接口的使用中,接口变量可以代表任何实现了该接口的类的

5、对象。这就相当于把类根据其实现的功能来分别代表,而不必顾虑类的具体继承层次。这样可以最大限度地利用动态绑定,隐藏实现细节。此外,Java 接口还可以用来实现不同类之间的常量共享。在一个类的继承层次结构中的任何一个类都可以实现一个接口,这个接口会影响此类的所有子类,但不会影响此类的任何超类。此类必须实现这个接口所定义的方法,而其子类可以从此类自动继承这些方法,当然也可以重写这些方法。从设计的角度来讲,Java 接口或抽象类一般用来作为一个类型的等级结构的起点。如果一个类已经有了一个主要的超类型,那么通过实现一个接口,这个类可以拥有另一个次要的超类型,这种次要的超类型叫做混合类型。下面介绍几种 J

6、ava 接口的常用方法,详细说明如下所示。单方法接口。接口中只有一个方法,一般用于描述特定的行为。标识接口。这种接口没有任何成员变量和方法,只用于标识特殊的类型。常量接口。在这种接口中没有任何方法,只有一些属性,由于在 Java 接口中的所有属性都被隐含地为 public sic final,因此这些属性都是常量。单方法接口在 Java 语言中应用广泛,如在 JDK 类库中定义的 Actionlistener 接口(包含在java.awt.event 包中)就只定义了一个方法,如下所示。ActionListener 接口是用于接收操作事件的器接口。对处理操作事件“感”的类可180publice

7、rface Actionlistenervoid actionPerformed(ActionEvent event);接口以实现此接口,而使用该类创建的对象可使用组件的 addActionListener()方法向该组件发生操作事件时,调用该对象的 actionPerformed(ActionEvent)方法。在再如定义多线程的 Runnable 接口(包含在 java.lang 包中)唯一定义了 run()方法,如下所示。任何希望实现多线程功能的类都需要实现 Runnable 接口,并编写 run()方法具体的执行逻辑。标识接口在 Java 语言中也得到了广泛的应用,例如,序列化接口 Se

8、rializable 就是一个标识接口,该接口的定义如下所示。任何实现了这个接口的类都是可以被序列化的,可以将对象保存在文件或数据库中。由于常量接口只包含了一些静态常量数据,没有任何方法,没有很好地体现面象的思想,在使用中也有很多不方便的地方,因此一般不使用。Java 是强类型的语言,Java 编译器会对代码进行检查,以确定每一次赋值、每一次方法的调用类型都是一致的。当发生任何不相符的情况时,Java 编译器就会提示错误。5.1.2接口的和使用Java 接口类似于抽象类,接口和抽象类也很相似,只定义了类中方法的原型,而没有直接定义方法的内容。具体的格式如下所示。acs modifyerface

9、 name extends name1, name2.acs:Java 方法控制符,可以是 private、default、protected、public 中的一个。modify:用于 Java 接口的修饰符只能是 abstract,一般情况下该修饰符被隐含于接口定义中,即没有必要显式地使用 abstract 关键字来修饰接口,因为接口本身就是抽象的。erface:Java 接口关键字,与.class 关键字类似,主要用于和定义 Java 接口。name:接口名。除了被当前作用域中的其他项使用的标识符以外,接口名可以是任何合法的标识符。extends:继承关系关键字,用于本接口的父接口,需要

10、注意的是,接口的继承和类的继承不同,接口可以有多个父接口。name1, name2.:父接口名,可以有多个父接口,中间用逗号分隔开。erface Body:接口主体,包含属性讲述。和方法定义,这部分内容将在后面的章节详细181erface Bodypublicerfaerializablepublicerface Runnablevoid run();下面定义了一个 A 接口,并了一个属性和一个方法。上例中定义了接口 A,并定义了 TEXT 属性和 method()方法。当要实现该接口时,需要在定义类时使用 implements 关键字,如下所示。一个类可以实现多个接口,如下面的例子定义了接口

11、 C,同时定义了 D 类来实现接口 A 和接口 C 的内容。5.1.3多继承在 Java 语言中,类之间只允许单继承,通过使用接口可以把一个类实现的接口也看做这个类的父类。类从实现的接口那里“继承”了变量和方法,尽管变量都是静态常量,方法都是未实现的原型。如果一个类实现的接口不止一个,那么所有这些接口类都将被视为父类。这样,实现了多个接口的类就相当于是从两个或两个以上的类派生出来的。Java 的多继承正是建立在 Java 接口之上的。通过实现接口,相当于只选择了一部分需要的属性和方法进行共享和继承,而不必通过父类与子类之间的继承关系将所有的特征全部传递给子类。因此,针对这一特性又可以把 Jav

12、a 的这种多继承称为“有选择的多继承”,这种多继承182publicerface Cpublic void pr();public class D implements A, Cpublic void method()System.out.prln(Implements A);public void pr()System.out.prln(Implements C);public class B implements Apublic void method()System.out.prln(Implements A);publicerface AString TEXT=erface; publ

13、ic void method();接口与一般的多继承相比更为精简,复杂度也大大降低了。在使用多继承时,一个子类可能会从不同的父类那里继承到同名的不同变量或方法,这种情况往往会引起两义性问题,即不知道子类中这样的变量或方法究竟继承了哪一个父类的版本。为了防止出现这样的两义性问题,在 Java 中规定不允许一个子类继承的父类的接口中定义同名的不同变量,否则编译该子类时将出错。而对于方法,由于接口类中定义的总是 abstract方法原型,没有实际代码,所以不会出现类似的两义性问题。相反,当接口类中要求实现的方法子类没有实现,而子类的父类中定义了同名方法时,编译器将子类从父类继承的该方法视为对接口的实

14、现。这样的继承都被认为是合法的。下面这个例子将定义两个接口 Car 和 Taxi,并且定义 NormalCar 类作为 Bus 类的父类,Bus类同时实现了 Car 和 Taxi 两个接口。(1)定义 Car 接口。(2)定义 Taxi 接口。(3)定义 NormalCar 类。(4)定义 Bus 类,继承 NormalCar 类,实现 Car 和 Taxi 接口。183class Bus extends NormalCar implements Car, Taxi /公共汽车类(Bus)继承NormalCar 类实现Car 和Taxi 接口privateWare;privateMan; pu

15、blicLoadWare()Ware=MAX_WEIGHT;returnWare;claormalCarSpeed=150;/一般车的最高时速为 150 千米/小时DriveSpeed()/获取汽车时速returnSpeed;erface Taxi/出租车接口MAX_NUMBER=4;/出租车最多能载 4 个人LoadMan();/上人erface Car/汽车接口MAX_WEIGHT=6;/最大载重 LoadWare();(5)定义erfaceDemo 类,使用上面定义的接口和类。通过上面这个例子可以看出,通过接口,公共汽车类实现了对一般汽车类、出租车类和小汽车类的继承,使得公共汽车具有一般

16、汽车的最高时速、出租车的最大载人数和小汽车的最大载货吨数。(6)编译与运行。将 Car 接口保存在 Car.java 文件中,Taxi 接口保存在 Taxi.java 文件中,NormalCar 类保存在 NormalCar.java 文件中, Bus 类保存在 Bus.java 文件中,erfaceDemo 类保存在 erfaceDemo.java 文件中,将这些文件都保存在默认目录中,首先在默认目录下执行 javac 命令编译文件。编译完成后,该目录下会出现相应的.class 文件,这时在默认目录下用 java 命令执行程序。程序的运行结果如下所示。184The max drive spe

17、ed of bus: 150 The max ware weight of bus: 6The max man number of bus: 4javaerfaceDemojavac Car.java javac Taxi.javajavac NormalCar.java javac Bus.javajavacerfaceDemo.javapublic classerfaceDemopublic sic void main(String args)Bus bus;/变量bus=new Bus();/生成对象System.out.prln(The max drive speed of bus:

18、+bus.DriveSpeed();/打印公共汽车的性能System.out.prln(The max ware weight of bus: +bus.LoadWare(); System.out.prln(The max man number of bus: +bus.LoadMan();publicLoadMan()Man=MAX_NUMBER;returnMan;接口5.2成员变量在接口中的使用Java 接口中成员变量的和定义格式如下所示。public sic final type name=value;public:表示属性是公共的,基于接口的特性,必须使用公共控制级别,使用任何其他

19、的级别都是错误的,在编译接口时会产生错误。由于 Java 接口所有的属性都是公共的常量,因此可以不用显式地属性为 public。sic:表示属性是静态的,与 public 关键字类似,可以不用显式地final:表示属性是不可变的,与 public 关键字类似,可以不用显式地属性为 sic。属性为 final。type:常量的数据类型,可以是任何合法有效的类型,包括新创建类的类型、Java 语言已经提供的各种类的类型,以及基本数据类型(整型、型等)。name:成员变量名,除了被当前作用域中的其他项使用的标识符以外,属性名可以是任何合法的标识符。value:常量的值,必须在时给其赋初始值。由于接口

20、内的所有属性都是 public、sic 和 final,因此可以很方便地利用这一点来创建一些常量,如下面的接口 Constants。在接口 Constants 中定义了 3 个常量,即 TEXT、MAX 和 MIN,在使用该接口时可以直接用“接口名.属性名”的方式。此外,可以使用表达式对接口中的成员变量进行初始化操作。5.3方法在接口中的使用Java 接口中成员变量的和定义格式如下所示。public abstract type name(parameter-list) throws-exception;public:表示方法是公共的,基于接口的特性,必须使用公共控制级别,使用任何其他的级别都是

21、错误的,在编译接口时会产生错误。可以不用显式地abstract:表示方法是抽象的,与 public 关键字类似,可以不用显式地方法为 public。方法为 abstract。type:方法返回的数据类型,可以是任何合法有效的类型,包括新创建类的类型、Java语言已经提供的各种类的类型,以及基本数据类型(整型、回任何值,则返回值 type 必须为 void。型等)。如果该方法不返name:方法名,除了被当前作用域中的其他项使用的标识符以外,方法名可以是任何合法的标识符。parameter-list:自变量列表,由一系列类型和标识符对组成,中间用逗号分开。自变量185publicerface Co

22、nstantsString TEXT=CONSTANTS; MAX=20;MIN=10;本质上是变量,接收方法被调用时传递给方法的参数值。如果方法没有自变量,那么自变量列表就为空。需要注意的是,由于在接口中的抽象方法具有 public控制级别,因此在类中实现此方法的时候必须将此方法为 public控制级别,否则无法通过程序编译。下面的例子中定义了接口 A 和该接口的实现 B 类,并定义了两个方法。将 A 接口保存在 A.java 文件中,B 类保存在 B.java 文件中, erfaceDemo类保存在erfaceDemo.java 文件中,将这些文件都保存在默认目录下,首先在默认目录下执行

23、javac 命令编译文件。在编译 B 类时出现错误,如下所示。186B.java:8: B 中的 getName() 无法实现 A 中的 getName();正在尝试指定更低的权限;为publicString getName() 1 错误javac A.java javac B.javaerface Avoid show(); String getName();class B implements Apublic void show()System.out.prln(Show);String getName()System.out.prln(getName); return Java 面象编程

24、。;public classerfaceDemopublic sic void main(String args)A a;a=new B();a.show();System.out.prln(a.getName();接口可见任何实现接口的方法必须为 public,修改后的 B 类如下所示。将 A 接口保存在 A.java 文件中,B 类保存在 B.java 文件中, erfaceDemo 类保存在erfaceDemo.java 文件中,将这些文件都保存在默认目录下,首先在默认目录下执行 javac 命令编译文件。编译完成后,该目录下会出现相应的.class 文件,这时在默认目录下用 java

25、命令执行程序。程序的运行结果如下所示。5.4接口与抽象类在 Java 语言中,抽象类和接口是支持抽象定义的两种不同的机制。正是这两种机制的存在,才赋予了 Java 语言强大的面象能力。抽象类和接口对抽象定义的支持具有很大的相似性,甚至可以相互替换,因此在进行抽象定义时对抽象类和接口的选择就显得比较随意。其实,这两种抽象定义的方式还是有很大区别的。抽象类和接口在 Java 语言中都是用来进行抽象定义的,在面象的概念中,所有的对象都是通过类来描述的。然而,并不是所有的类都是对象的,如果一个类中没有足够的信息来描述一个具体的对象,这样的类就是抽象类。抽象类常常用来表示在对问题领域进行分析、设计时得出

26、的抽象概念,是对一系列看上去不同但本质上相同的具体概念的抽象。例如,当进行一个图形编辑的开发时,在问题领域存在着圆、三角形等这样一些具体概念,虽然各自都有不同的属性和行为,但又都属于形状这一概念,形状这个概念就是一个抽象概念。正187Show getNameJava 面象编程。javaerfaceDemojavac A.java javac B.javajavacerfaceDemo.javaclass B implements Apublic void show()System.out.prln(Show);public String getName()System.out.prln(get

27、Name); return Java 面象编程。;是因为抽象概念在问题领域没有对应的具体概念,所以用以描述抽象概念的抽象类是不能够被实例化的。5.4.1语法定义上的不同在语法定义的层面,Java 语言对于抽象类和接口给出了不同的定义方式,首先定义了一个名为 AbstractDemo 的抽象类,如下所示。接着定义了名为erfaceDemo 的接口,如下所示。在抽象类方式中,AbstractDemo 类可以有自己的数据成员,也可以有非 abstract 成员方法,而在接口方式的实现中erfaceDemo 接口只能有静态的、最终的数据成员,即 sic final常量,所有的成员方法都是 public

28、 和 abstract。从某种意义上说,接口是一种特殊形式的抽象类。抽象类和接口都可以用来实现面别有以下几个方面。象的,但是在具体使用上还是有区别的,主要区抽象类在 Java 语言中表示的是一种继承关系,由于 Java 的单继承机制使得每个类只能使用一次继承关系,而每个接口的继承关系却可以有很多个。在抽象类的定义中,可以赋予方法默认行为。但是在接口的定义中,方法不能拥有默认行为。在接口中没有默认的行为就会造成一些问题,因为如果以后想修改类的界面来适应新的情况新的功能,可能要花费很多时间。但如果界面是通过抽象类来实现的,那么可能只需要修改定义在其中的默认行为就可以了。5.4.2设计角度上的不同前

29、面主要从语法定义和编程的角度论述了抽象类和接口的区别,本节将从设计角度来分析两者的区别,从这个层面进行分析才能更深入地理解两者概念的本质。抽象类在 Java 语言中体现了一种继承关系,要想使继承关系合理,父类和子类之间必须存188publicerfaceerfaceDemopublic void method1(); public void method2();public abstract class AbstractDemopublic abstract void method1(); public abstract void method2();接口在 is-a 的关系,即父类和子类在概

30、念本质上应该是相同的。接口并不要求其实现者和接口定义在概念本质上是一致的,只要实现了接口定义的方法即可。为了使论述便于理解,下面将通过一个简单的实例进行说明。假设在问题领域中有一个关于门(Door)的抽象概念,门具有开启和关闭这两个主要的行为,可以通过抽象类和接口来定义一个表示该抽象概念的类型,定义方式分别如下所示。首先,使用抽象类方式定义 Door。其次,使用接口方式定义 Door。其他具体的 Door 类型可以是由 extends 关键字使用抽象类方式定义的 Door 或者是由implements 关键字使用接口方式定义的 Door。如果不需要新增任何功能新的行为,使用抽象类和接口这两种方

31、式基本上没有区别。当要求 Door 还具有功能时,分别从抽象类和接口两个设计角度来实现具体的功能。首先,简单地在 Door 的定义中增加一个 alarm()方法,如下所示。下面分别以继承抽象类接口这两种方式定义了具有功能的 AlarmDoor 类。189public class AlarmDoor extends Doorvoid open()System.out.prln(Door Open);abstract class Doorabstract void open(); /开启 abstract void close(); /关闭 abstract void alarm(); /erfa

32、ce Doorvoid open();/开启void close();/关闭void alarm();/erface Doorvoid open();/开启void close();/关闭abstract class Doorabstract void open();/开启 abstract void close();/关闭这种方式了面象设计中的 ISP 原则,在 Door 的定义中把门概念本身固有的行为方法和另外一个概念“器”的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door 这个概念的模块会因为“器”概念的改变而改变。因为 open、close 和 alarm 属于两个不同领

33、域的概念,根据 ISP 原则应该分别将其定义在代表这两个概念的抽象类中。这样就可以分为 3 种方式,如下所示。将两个概念都使用抽象类方式定义。将两个概念都使用接口方式定义。将一个概念使用抽象类方式定义,另一个概念使用接口方式定义。显然,由于 Java 语言不支持多重继承,所以两个概念都使用抽象类方式定义是不可行的。后两种方式都是可行的,但是使用哪种方式将反映出对于问题领域中的概念本质的理解,以及对于设计意图的反映是否正确、合理。如果两个概念都使用接口方式来定义,那么就反映出两个方面,如下所示。可能没有理解清楚问题领域,AlarmDoor 在概念本质上到底是门还是器。如果通过对问题领域的分析发现

34、 AlarmDoor 在概念本质上和 Door 是一致的,那么在实现时就没有正确地揭示设计意图,因为这两个概念都使用接口的方式定义述含义。出上190void close()System.out.prln(Door Close);void alarm()System.out.prln(Door Alarm);class AlarmDoor implements Doorpublic void open()System.out.prln(Door Open);public void close()System.out.prln(Door Close);public void alarm()Syst

35、em.out.prln(Door Alarm);接口AlarmDoor 在概念本质上是 Door 的一种,即具备 is-a 的关系,同时又具有的功能。所以对于 Door 这个概念,应该使用抽象类的方式来定义。另外,AlarmDoor 又具有功能,即能够完成概念中定义的行为,所以概念可以通过接口方式来定义,如下所示。上面定义了一个抽象类 Door、一个接口 Alarm的 DoorDemo 类,详细说明如下:类 AlarmDoor 及使用 AlarmDoor 类Door 被定义为抽象类,Alarm 被定义为接口,了 open()、close()方法。了 alarm()方法。191abstract

36、class Doorabstract void open();/开启 abstract void close();/关闭erface Alarmvoid alarm();/class AlarmDoor extends Door implements Alarmvoid open()System.out.prln(Door Open);void close()System.out.prln(Door Close);public void alarm()System.out.prln(Door Alarm);public class DoorDemopublic sic void main(St

37、ring args)AlarmDoor door; door=new AlarmDoor(); door.open();door.close();door.alarm();AlarmDoor 本质上是 Door 的一种特殊情况,因此 AlarmDoor 类继承自 Door 类。AlarmDoor 具备行为,因此实现了 Alarm 接口。DoorDemo 类使用了 AlarmDoor 类,并依次调用了 3 个方法。将 Door 抽象类保存在 Door.java 文件中,Alarm 接口保存在 Alarm.java 文件中,AlarmDoor类保存在 AlarmDoor.java 文件中,Door

38、Demo 类保存在 DoorDemo.java 文件中,将这些文件都保存在默认目录下,首先在默认目录下执行 javac 命令编译文件。编译完成后,该目录下会出现相应的.class 文件,这时在默认目录下用 java 命令执行程序。java DoorDemo程序的运行结果如下所示。上面这种实现方式基本上能够明确地反映出对问题领域的理解,正确地揭示设计意图。从含义上看,抽象类表示的是 is-a 关系,接口表示的是 like-a 关系。5.4.3深入理解接口和抽象类抽象类和接口是 Java 语言中定义抽象概念的两种方式,它们有很大的相似性,但在语法定义、使用角度,以及设计角度方面有所不同。抽象类在

39、Java 语言中表示的是一种继承关系,一个类只能使用一次继承关系,但是,一个类却可以实现多个接口。在抽象类中可以有成员变量,也可以有非 abstarct 的方法,而在方法中,只能有静态的最终的成员变量,所有的方法都是 abstract。抽象类与接口反映出的设计理念不同。实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法,但接口中则不能有任何具体的实现方法。接口中定义的变量默认是 public s ic final 类型,且必须给其赋初值,因此实现类中不能重新定义,也不能改变其值。抽象类中的变量可以在子类中被重新定义,也可以被重新赋值。接口中的方法默认都是 public abs

40、tract 类型的。5.5基于接口的多态前面的内容主要讲述了基于继承的多态概念,本节将着重说明基于接口的多态概念。由于接口反映的也是一种特殊的抽象概念,因此可以采用接口来实现多态性。下面的例子中定义了形状抽象类(Sh)和绘制接口(Paable),并定义了两个具体的实现类。192Door Open Door CloseDoor Alarmjavac Door.java javac Alarm.java javac AlarmDoor.javajavac DoorDemo.java接口abstract class Shabstract double area(); abstract double

41、length();erface Paable/计算面积/计算边长void pa();/绘制class Rectangle extendsprivate double i; private double j;ShimplementsPaable/长/宽/构造函数。Rectangle(doublethis.i=i; this.j=j;double area()return i*j;double length()i,doublej)/计算面积/计算边长return (i+j)*2;public void pa()System.out.prln(Rectangle/绘制Pa!);class Squar

42、e extends Shprivate double i; Square(double i)this.i=i;double area()implementsPaable/边长/构造函数/计算面积retur;double length()/计算边长193上面定义了抽象类 Sh和接口 Paable,并定义了两个具体实现类 Rectangle 类和 Square类,最后了使用这些接口和类的 ShDemo 类,详细说明如下:Sh为抽象类,定义了 area()方法和 length()方法。Paable 为接口,定义了 pa()方法。Rectangle 类为 ShSquare 类为 Sh类的子类并实现了

43、Paable 接口。类的子类并实现了 Paable 接口。ShDemo 类定义了一个 Paable 接口变量 p。首先生成了 Rectangle 类的对象并将 p 指向该对象。通过强制类型转换调用 Rectangle 类的 area()方法计算面积(Rectangle)p).area()。通过强制类型转换调用 Rectangle 类的 length()方法计算边长(Rectangle)p).length()。直接调用了 Paable 接口的 pa()方法,但是这里由于 p 指向的对象为 Rectangle 类的对象,因此将执行 Rectangle 类的 pa()方法。194return i*4

44、;public void pa()/绘制System.out.prln(Square Pa!);public class ShDemopublic sic void main(String args)Paable p;/接口变量p=new Rectangle(3.0,4.0);/生成矩形对象 double area;double length;area=(Rectangle)p).area();/面积 length=(Rectangle)p).length();/边长 System.out.prln(Rectangles area: +area); System.out.prln(Rectan

45、gles length: +length); p.pa();/绘制p=new Square(3.0);/生成正方形对象area=(Square)p).area();/面积length=(Square)p).length();/边长 System.out.prln(Squares area: +area); System.out.prln(Squares length: +length); p.pa();/绘制接口生成了 Square 类的对象并将 p 指向该对象。通过强制类型转换调用 Square 类的 area()方法计算面积(Square)p).area()。通过强制类型转换调用 Squa

46、re 类的 length()方法计算边长(Square)p).length()。直接调用了Paable 接口的pa()方法,但是这里由于 p 指向的对象为Square 类的对象,因此将执行 Square 类的 pa()方法。将 Sh抽象类保存在 Sh.java 文件中,Paable 接口保存在 Paable.java 文件中,Rectangle 类保存在 Rectangle.java 文件中,Square 类保存在 Square.java 文件中,ShDemo 类保存在 ShDemo.java 文件中,将这些文件都保存在默认目录下,首先在默认目录下执行 javac命令编译文件。编译完成后,该目

47、录下会出现相应的.class 文件,这时在默认目录下用 java 命令执行程序。程序的运行结果如下所示。Squares area: 9.05.6接口与回调其他程序语言(如 C、C+)中都有一些传递某种事件发生时调用的函数指针,Java 语言虽然并不支持方法指针,但是提供了另外式来实现回调机制。在 Java 语言中,接口支持并提供了一种与获得回调具有等价功能的机制,即定义一个简单的接口,并在该接口中调用的方法。例如,假定希望在某个事件发生时得到通知,可以定义一个接口。要上面的 Event 接口只定义了一个 doEvent(String)方法,任何实现该接口的类都必须完整地实现该方法的型信息。逻辑

48、,这样就可以控制实现该接口的类的任何对象,而不必关心任何外部类发出事件信号的类必须等待实现了 Event 接口的对象,并在适当的时候调用 doEvent(String)方法,而且还要传递一个字符串对象进入该方法。195publicerface Eventvoid doEvent(String s);Squares length: 12.0Square Pa!Rectangles area: 12.0Rectangles length: 14.0 Rectangle Pa!java ShDemojavac Sh.java javac Paable.java javac Rectangle.jav

49、a javac Square.javajavac ShDemo.java希望接收事件通知的类必须实现 Event 接口,并将自身传递给事件通知类。下面就是实现了该接口的 TestEvent 类。TestEvent 类实现了前面定义的 Event 接口,并完整地描述了 doEvent(String)方法的处理逻辑,详细说明如下:通过使用 implements 关键字,使 TestEvent 类实现了 Event 接口。通过 new EventNotifier(this)将自身传递给事件通知类并生成相应的对象。由于 Event 接口中只有 doEvent(String)方法,因此 TestEven

50、t 类实现了该方法。方法中首先了一个字符串临时变量 ns。将方法传入的字符串转换为大写,并将 ns 指向了这个新生成的对象。将新生成的字符串对象显示出来。下面EventDemo 类使用以上定义的接口和类,实现回调机制。196public class TestEvent implements Eventprivate EventNotifier notifier; /事件通知对象 public TestEvent()this.notifier=new EventNotifier(this);/通过 TestEvent 对象生成事件通知对象public void doEvent(String s)

51、/实现接口方法String ns; ns=s.toUpperCase();System.out.prln(s.toUpperCase(): +ns);public EventNotifier getNotifier()return this.notifier;public class EventNotifierprivate Event event;public EventNotifier(Event event)this.event=event;/保存事件对象以备后用public void doWork(String s)/事件通知event.doEvent(s);接口上面的 EventDe

52、mo 类使用了 TestEvent 类和 EventNotifier 类,详细说明如下:定义了 TestEvent 对象的变量 event。生成了 TestEvent 类的对象,并将 event 指向该对象。了事件通知对象的变量。通过 TestEvent 类的 getNotifier()方法获取了事件通知对象。方法,即 doWork(String)方法。通过事件通知对象调用了相应在调用这个方法后将通过 Event 接口的 doEvent(String)方法调用具体对象的实现方法,这里将调用 TestEvent 类的相应方法。将 Evnet 接口保存在 Evnet.java 文件中,TestEv

53、ent 类保存在 TestEvent.java 文件中,EventNotifier 类保存在 EventNotifier.java 文件中,EventDemo 类保存在 EventDemo.java 文件中,将这些文件都保存在默认目录下,首先在默认目录下执行 javac 命令编译文件。编译完成后,该目录下会出现相应的.class 文件,这时在默认目录下用 java 命令执行程序。程序的运行结果如下所示。从上面例子的运行结果可以看出事件通知对象回调了 Event 接口的方法,具体执行的是TestEvent 类的 doEvent(String)方法,将字符串中的字符变为大写格式。所谓接口回调,是指

54、可以把使用实现了某一接口的类创建的对象的赋给该接口的接口变量,那么该接口变量就可以调用被类实现的接口中的方法。实际上,当接口变量调用被类实现的接口中的方法时,就是通知相应的对象调用接口的方法,这一过程称为对象功能的接口回调。下面定义了一个名为的接口,并定义了两个类实现了接口。197erfacevoid desc();/说明s.toUpperCase():ERFACE CALLBACKjava EventDemojavac Evnet.javajavac EventNotifier.javajavac TestEvent.java javac EventDemo.javapublic class

55、 EventDemopublic sic void main(String args)TestEvent event;/TestEvent 对象event=new TestEvent();EventNotifier notifier;/事件通知对象 notifier=event.getNotifier();String s;s=erface Callback;notifier.doWork(s);/调用事件通知对象方法将接口保存在.java 文件中,Student 类保存在 Student.java 文件中,Teacher类保存在 Teacher.java 文件中,Demo 类保存在Demo.

56、java 文件中,将这些文件都保存在默认目录下,首先在默认目录下执行 javac 命令编译文件。198javac.java javac Student.java javac Teacher.java javacDemo.javavoid work();/工作class Student implements/学生类public void desc()System.out.prln(我是学生!);public void work()System.out.prln(上学!);class Teacher implements/老师类public void desc()System.out.prln(我

57、是老师!);public void work()System.out.prln(教书!);public classDemopublic sic void main(String args)a;接口变量a=new Student();/实例化,接口变量中存放对象的a.desc();/接口回调a.work();/接口回调a=new Teacher();/实例化,接口变量中存放对象的a.desc();/接口回调a.work();/接口回调接口编译完成后,该目录下会出现相应的.class 文件,这时在默认目录下用 java 命令执行程序。程序的运行结果如下所示。5.7instanceof 的使用ins

58、tanceof 是 Java 语言中的一个二元操作符,与“=”、“”、“”等类似,主要用于比较左边的对象是否是右边类的实例,返回类型的数据。instanceof 操作符的作用是判断一个变量是否是指定类的对象,由于 Java 语言具有多态性,因此在程序中可以用一个子类的实例赋值给一个父类的对象变量,而在有些情况下需要判断变量到底是一个什么类型的对象,这时就可以使用 instanceof 关键字。当左操作数是右操作数的类的实例或者是子类的实例时将返回真,如果是将一个子类的实例赋值给一个父类的变量,用 instanceof 判断该变量是否是子类的一个实例时也将返回真。instanceof 关键字的使

59、用规则如下所示。result:变量,instanceof 表达式最终的运算结果为类型的数据。object:对象,用于比较的对象。.class:用于比较的类。下面的代码段首先定义了一个字符串变量 s,接着使用 instanceof 关键字判断其是否是字符串类型的对象。由于 s 本身定义的就是 String 类型,因此最终 isString 变量将为 true。下面的这个例子使用了上一节中定义的接口、Student 类。if(b)199public class InstanceofDemopublic sic void main(String args)p;p=new Student();b;b=

60、p instanceof;String s;s=I AM a String!;isString;isString=s instanceof String;result;result=object instanceof class我是学生!上学!我是老师!教书!javrsonDemo将 InstanceofDemo 类保存在 InstanceofDemo.java 文件中,将文件保存在默认目录下,首先在默认目录下执行 javac 命令编译文件。编译完成后,该目录下会出现相应的.class 文件,这时在默认目录下用 java 命令执行程序。程序的运行结果如下所示。由于instanceof类型的对象

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论