390 likes | 750 Views
Java 程序设计 案例教程. 第 05 章. 北京大学出版社. 第 05 章 Java 接口与包. 教学目标. Java 语言的接口 接口的定义 接口的实现 Java 语言的包 包的创建与使用. 5.1 Java 语言 的接口与包. 5.1.1 接口的定义 Java 中不允许有多重继承,即如果一个类有父类的,它只能有一个父类。但 Java 并没有限制从多个类中分别继承特性的自由和方便,因此提供了接口这个机制。
E N D
Java程序设计案例教程 第05章 北京大学出版社
第05章 Java接口与包 教学目标 • Java语言的接口 • 接口的定义 • 接口的实现 • Java语言的包 • 包的创建与使用
5.1 Java语言的接口与包 5.1.1 接口的定义 • Java中不允许有多重继承,即如果一个类有父类的,它只能有一个父类。但Java并没有限制从多个类中分别继承特性的自由和方便,因此提供了接口这个机制。 • 接口(interface)是类的另一种表现方式,它是一种特殊的“类”,更确切地说,它是抽象类功能的另一种实现方法,可将其想象为一个“纯”的抽象类。
接口的定义: [public] interface 子接口名[extends 父接口名列表] { //接口体 //数据成员声明 //抽象方法声明 [public][abstract][native]返回值 方法名(参数列表)[throw 异常列表]; } 一个类只能有一个父类,但它可同时有多个接口,实现多重继承。 注意:所有属性都必须是public、static、final类型;所有方法都必须是public、abstract 类型。
例5-1 在系统定义的接口——DataInput定义语句。 public interface java.io.DataInput { public abstract boolean readBoolean( ); //读入布尔型数据 public abstract byte readByte( ); //读入字节型数据 public abstract char readChar( ); //读入字符型数据 public abstract double readDouble( ); public abstract float readFloat( ); public abstract void readFully(byte b[] ); //读入全部数据存入字节数 public abstract void readFully(byte b[],int off, int len); public abstract int readInt( ); public abstract String readLine( ); public abstract long readLong( ); public abstract short readSshort( ); public abstract int readUnsignedByte( ); public abstract int readUnsignedShort( ); public abstract String readUTF( ) public abstract int skipBytes(int n); //将读取位置跳过n个字节 }
注意以下几点: (1) 接口定义用关键字interface而不是class。 (2) 修饰符public用来指明任意一个类都可以调用此接口;若无此修饰符,则只有那些与本接口在同一个包中的类才能访问它。 (3) 接口体中的数据成员全是用final static修饰的,即它们一定是给出标识符的常量,即使在定义时未写也是如此。 (4) 接口体中定义的方法都是抽象方法。 (5) 接口没有构造方法。 (6) 接口也具有继承性,且一个接口可以继承多个父接口。(这点与类的继承不同。)
5.1.2 接口的实现 因为没有方法体,所以接口必须被继承,在实现接口的类中必须实现那些抽象方法,给出方法具体的实现细节。实现接口的这些类的实例对应的是一种代码实现,即使有同名同参数类表的方法也不会再产生混乱。
实现接口应注意以下问题。 (1) 用implements声明该类将要实现哪些接口。 (2) 若实现某接口不是abstract类,则在类定义部分必须实现指定接口的所有抽象方法。即为所有抽象方法定义方法体,而且方法头部分应该与接口中的定义完全一致,即有完全相同的返回值和参数列表。 (3) 若实现某接口是abstract类,则它可以不实现该接口的方法。 (4) 一个类在实现某接口的抽象方法时,必须使用完全相同的方法头。 (5) 接口的抽象方法的访问修饰符都已指定为public,所以类在实现方法时,必须显示地使用public修饰符,否则将被系统警告。
用户定义类的完整格式 [修饰符] class 类名[extends父类名] [implements 接口名列表] { [修饰符] 数据成员; //声明及初始化 [修饰符] 方法成员; //声明及方法体 } • 引发接口的名字冲突,一般系统将按以下方式处理 (1) 父接口中有同名的有名常量,使用指定具体有名常量的格式:<接口名>. <常量名>。 (2) 若两个直接父接口中包含有相同名但返回类型不同方法,那么将引发编译错误。 (3) 若两个直接父接口中包含有相同名且返回类型相同的方法,那么类中只能继承保留一个。
例5-2 实现接口应用程序。 interface A{ //接口A定义 String a= "接口A中的常量"; void showA(); adstract void setAColor(); } interface B extends A{ //接口B定义,继承A String b="接口B中的常量"; void showB(); adstract void setBColor(); } interface C extends B{ //接口C定义,继承B String c="接口C中的常量"; void showC(); adstract void setCColor(); }
class implnterfaceABC implements C{ //类实现接口 public void showA() { System.out.println(); } public void setAColor() { System.out.println("设置的是接口A的颜色!"); } public void showB() { System.out.println(); } public void setBColor() { System.out.println("设置的是接口B的颜色!"); } public void showC() { System.out.println(); } public void showC() { System.out.println(); } public void setCColor() { System.out.println("设置的是接口C的颜色!"); } }
public class interfacelnheritanceTest{ public static void main(String[] args){ implnterfaceABC intf=new implnterfaceABC(); intf.showA(); intf.setAColor(); intf.showB(); intf.setBColor(); intf.showC(); intf.setCColor(); } }
设计类的过程中,应该注意如下事项 (1) 类的定义与实现是放在一起保存的,整个类必须保存在一个文件中。 (2) 公共类名即是文件名。 (3) 新类必须在已有类的基础上构造。 (4) 在已有类的基础上构造新类的过程称为派生。 (5) 派生出的新类称为已有类的子类。 (6) 子类继承父类的方法和属性。 (7) 当没有显式指定父类时,父类隐含为Java.lang包中的Object类。Object类是Java中唯一没有父类的类,是所有类的父类。 (8) 使用extends可以继承父类的数据成员和方法成员,形成子类,也就是说子类是父类派生出来的。
抽象类和接口的主要区别 (1) 在接口中所有的方法都是抽象方法,都没有方法体;而在抽象类中定义的方法可以不限于抽象方法。 (2) 接口中定义的成员变量都默认为终极类变量,即系统会为其自动增加final和static这两个关键字,并且对该变量必须设置初值,而抽象类中没有此限制。 (3) 一个类只能由唯一的一个类继承而来,但可以实现多个接口。 • 抽象类和接口相似之处: 二者都不能实例化。
5.1.3 接口回调 • 接口回调是指把实现某一接口的类创建的对象的引用赋给该接口声明的接口变量中。那么该接口变量就可以调用被类实现的接口中的方法。 • 实际上,当接口变量调用被类实现的接口中的方法时,就是通知相应的对象调用接口的方法。
例5-3 在使用接口回调技术。 interface ShowMessage{ void ShowSB(String s); } class TV implements ShowMessage{ public void ShowSB(String s){ System.out.println(s); } } class PC implements ShowMessage{ public void ShowSB(String s){ System.out.println(s); } } public class Test_ex{ public static void main(String args[]) { ShowMessage sm; //声明接口变量 sm=new TV(); //接口变量中存放对象的引用 sm. ShowSB("电视机"); //接口回调 sm=new PC(); //接口变量中存放对象的引用 sm. ShowSB("三星A5000"); //接口回调 } }
5.1.4 节小结 • 接口的定义和实现。在Java程序设计中,一个类只 能有一个父类,这样程序结构简单,层次清楚。但 实际中往往需要多重继承,因此Java提供了接口用 于实现多重继承,一个类可以有一个父类和多个接口。 • 接口定义 [修饰符] interface <接口名>{ 接口体 } • 接口实现 class <类名> implements <接口1>,<接口2>,…{ 类体 }
5.2 Java包 • Java程序设计就是定义类的过程。 • 包含 :系统定义好的类和用户自行定义的类。 • 包是类和接口的一种松散集合。 • 使用包的主要目的是实现不同程序之间类的重用。
5.2.1 创建包 • 创建无名包 系统自动为每个.java源文件创建一个无名包。该.java 源文件中定义的所有类隶属于这个包,它们之间(除private, protect类型外)可以相互引用。 注意:无名包中的类不能被其他包中的类使用和复用。 • 创建有名包 创建有名包时,必须在整个源文件的第一行完成。 明语句格式: package 程序包名; 例如:package CardSystem; //在当前文件夹下建立子文件夹CardSystem package CardSystem .CardClasses; //在当前文件夹的子文件夹CardSystem下建立子文 件夹CardClasses
5.2.2 使用包 • 使用包名、类名前缀 • 在同一个类中,在要使用的属性或方法名前加上类名作为前缀。 • 若要使用其他包中的类,须在类名前再加上包名作为前缀。 • 例如: • CardClasses.D200 my200=new CardClasses.D200(12345,12); • System.out.println(my200.toString( )); • 加载需要使用的类 • 使用import语句将需要使用的整个类加载到当前程序中。 • 例如: • import CardClasses.D200; //在程序开始加载其他包的类 • D200 my200=new D200(12345, 12); • 加载整个包 • 先设置包的路径;使用import语句加载其他包中的一个类或引入整个包,格式如下: • import 程序包名.类名; • import 程序包名.* ;
包的访问权限 一个包中只有访问权限为public的类才能被其他包引用 (创建此类的对象),其他有默认访问权限的类只能在同一个包中使用。 (1)public类的成员 public类的public成员可以被其他包的代码访问。 它的protected成员可以被由它派生的在其他包中的子类访问。 (2)默认访问权限类的成员 默认访问权限类的成员,不能被其他包的代码访问。
常用类——System系统类 用System类获取标准输入/输出,System类的3个属性如下所述。 (1) public static PrintStream err; //标准错误输出 (2) public static InputStream in; //标准输入 例如:char c=System.in.read( ); (3) public static PrintStream out; //标准输出 例如:System.out.println(“Hello! Guys.”);
常用类——Runtime运行时类 Runtime类可以直接访问运行时的资源,如totalMemory()方法可以返回系统的内存总量,freeMemory()方法可以返回内存的剩余空间。
Class类提供运行的信息,例如名字、类型及父类等。Class类提供运行的信息,例如名字、类型及父类等。 • 例如:this.getClass().getName();可以得到当前对象的类名。当前对象(this)调用Object类的getClass()方法,得到当前对象的类返回给Class类,再调用Class的getName()方法,得到当前对象的类名。 • ClassLoader类提供把类装入运行环境的方法。 • 常用类——类操作类Class和ClassLoader
常用类——Date时间和日期类 Date类的构造方法Date()可获得系统当前日期和时间。
常用类——Calendar类 Calendar类可以将Date()对象的属性转换成YEAR、MONTH、DATE和DATE_OF_WEEK等常量。 Calendar类没有构造方法,可以用getInstance()方法创建一个实例,再调用get方法和常量获得日期或时间的部分值。
5.2.3 节小结 • 包是类的逻辑组织形式。在程序设计中,可 用系统提供的包,也可声明类所在的包,同一个包中类的名字不能重复。 • 包是有等级的,即包中可以有包。 • 创建和包的使用,要求不仅会引入系统包,还能自己创建包或引用其他设计者设计的包。 • 包的引用有两种方法: 一种是用import语句引用; 一种是使用包名、类名做前缀进行引用。
5.3 综合应用案例 单位主管对各类支出基本价格的了解管理程序。 interface Income{ publicvoid getFee(); } interfaceAdjustTem{ publicvoid controlTemperature(); } class BusimplementsIncome{ publicvoid getFee(){ System.out.println("公共汽车:1元/张,不计算千米数"); } } classTaxtimplementsIncome,AdjustTem{ publicvoid getFee(){ System.out.println("出租车:1.60元/千米:起价3千米"); } publicvoid controlTemperature(){ System.out.println("安装了haier空调:8700元/台"); } } 案例5.3.1
classCinemaimplementsIncome,AdjustTem{ publicvoid getFee(){ System.out.println("电影院:门票,10元/张"); } publicvoid controlTemperature(){ System.out.println("安装了中央空调:27567元。"); } } publicclassTest_interface1{ publicstaticvoid main(String args[]){ Bus ql=new Bus(); Taxt dzh=new Taxt(); Cinema hx=new Cinema(); ql.getFee(); dzh.getFee(); hx.getFee(); dzh.controlTemperature(); hx.controlTemperature(); } } 案例5.3.1
案例5.3.2 获取当前年份、出生年份程序 文件Date.jave中的代码: package Firstpackage; import java.util.*; //导入Java的实用包中所有的类 publicclass Date{ //声明Date 类 privateint year,month,day; public Date(int y,int m,int d){ year=y; month=m; day=d; } public Date(){;} publicint thisyear(){ //方法thisyear得到当前年份 return Calendar.getInstance().get(Calendar.YEAR); } }
案例5.3.2获取当前年份、出生年份程序 文件Person_ex.java中的代码: import Firstpackage.*; //导入Firstpackage的实用包中所有的类 class Person{ //声明Person String name; int age; public Person(String na,int ag){ name=na; age=ag; } public Person(){;} publicint birth(int y){ //此方法得到出生的年份 return y-age+1; } } publicclass Person_ex{ publicstaticvoid main(String args[]){ Person ps=new Person("Tom ",21); Date now=new Date(); //创建包Firstpackage中类Date的对象 int y=now.thisyear(); System.out.println(ps.name+"was born in "+ps.birth(y)); } }
5.4 章小结与重点 • 通过对接口和包的学习,使得Java程序设计更加灵活完整; • 重点学习了接口的定义和实现; • 接口用于实现多重继承,接口的声明是由interface关键字定义的;接口的实现是由类声明语句中implements关键字实现的。 • 在程序设计中使用和设计包。包引用两种方法: 一种是用import语句引用;另一种是使用包名、类名做前缀进行引用。
5.5 章习题 • 简答题 • Java实现多重继承的机制是什么?怎么实现? • 什么是抽象类?什么是抽象方法? • Java的接口有什么特点? • 编写程序 • 以电话类为父类,移动电话和固定电话为两个子类,并使移动电话实现接口:可移动。固定电话又有子类:无绳电话。定义这几个类,明确它们的继承关系。
5.6 章综合实验项目 • 实验项目: 区分能力的接口程序。 • 实验要求: • 利用接口继承完成生物(Biology)、动物(Animal)、人(Man)3个接口的定义。其中Biology接口定义一个抽象方法breath(),Animal接口定义两个抽象方法sex()和ate(),Man接口定义两个抽象方法think()和study();定义一个NormalMan类实现上述3个接口中定义的抽象方法。