1、JAVA程序设计与实训教程第六章 Java面向对象高级编程n6.1 类的继承n6.2 类的多态n6.3 接口n6.4 包n6.5 Java的类库 6.1 类的继承n通过继承可以更有效的组织程序结构,明确类间关系,并充分利用已有的类来完成更复杂、深入的开发。nJava语言以Object类作为所有类的最高父类,所有的类都是直接或间接的继承Object类得到的。nJava提供不同层次的标准类,使用户可以按需要派生自己的类。6.1.1 继承的概念n定义:继承是程序中两个类间的一种关系,在定义一个类时,如果指明了类A继承了类B(B已存在),则类A通常就拥有了类B的成员属性和成员方法,此时称类A和类B间具
2、有继承的关系。n直接父类(直接超类):被继承的类B称为类A的直接父类。父类包括所有直接或间接被继承的类。n子类、次类、衍生类:继承于父类的类。子类继承父类的状态和行为,同时也可以修改父类的状态或重写父类的行为,并添加新的状态和行为。理解继承:交通工具交通工具 汽车汽车 卡车卡车旅行车旅行车 小汽车小汽车 轿车轿车 跑车跑车 面包车面包车6.1.1 继承的概念n指明继承关系后,父类中的属性(成员)就无须在子类中重复描述,从而实现了一定程度的代码的复用。nJava语言是单继承机制:在Java的继承层次中,一个父类可以有多个直接子类,但一个子类只能有一个直接父类,即Java不支持多重继承。nJava
3、的类继承不改变成员的访问权限,父类中的成员为公有的(public)或被保护(protected)的,则其子类的成员访问权限也即成为公有的或被保护的,而父类中的私有的(private)成员变量是不能被继承来的。6.1.2 继承的实现n1.继承的实现n2.子类继承父类的原则n3.构造方法的继承1.继承的实现n在类头的定义处用extends关键字来实现类间的继承。n格式:n修饰符 class 新类名 extends 父类名nextends为java的关键字,声明了新定义的类为一个已经存在类的子类。n如果缺省extends子句,则该类为java.lang.Object的子类.n例:6.12.子类继承父
4、类的原则n直接子类继承直接父类应遵循的原则:n(1)直接子类继承那些被声明为public或protected的直接父类成员。n(2)直接子类继承同一包中父类里无访问控制修饰符的成员(包括变量和方法)。n(3)子类不能继承父类中被private修饰的成员。n(4)若子类中声明了一个与父类同名的成员,则子类不再继承该父类中的该同名的成员。3.构造方法的继承n在创建子类的对象时,使用子类的构造方法对其初始化,不但要对自身的成员变量赋初值,还要对父类的成员变量赋初值。nJava中允许子类继承父类的构造方法。继承原则有三条。继承原则:n(1)若父类是无参数的构造方法,则子类无条件的继承该构造方法。n(2
5、)若子类无自己的构造方法,则它将继承父类的无参数构造方法作为自己的构造方法;若子类有自己的构造方法,则在创建子类对象时,它将先执行继承自父类的无参数构造方法,然后执行自己的构造方法。n(3)若父类是有参数的构造方法,子类可以通过在自己的构造方法中使用super关键字来调用它,但这个调用语句必须是子类构造方法的第一个可执行语句。n例:6.26.1.3 变量的隐藏n定义:子类对从父类那里继承来的变量重新加以定义称为变量的隐藏。n当在子类中定义了与父类中同名的成员变量时,若在子类中访问此变量,则父类中的同名变量被隐藏,访问的是子类中定义的同名变量,而非父类中的。n如一定要引用父类中的被隐藏的变量,可
6、使用super关键字。n例:6.36.1.4 方法的覆盖n定义:子类定义了与父类中同名的方法时,则父类中的方法被覆盖,即方法的结果是子类方法的执行结果。n例:6.46.1.5 this和super关键字n1、this的用法n(1)this代表他所在的类本身的实例对象,相当于类对象的另一个名字,利用this可以调用当前对象的方法和变量。n特:当方法的参数与成员变量重名且该方法中同时使用参数和访问该方法所属类的成员变量时,无法区分哪一个是形参名,哪一个是变量名,这时要用到this。n例:6.56.1.5 this和super关键字n(2)可用this来调用它所在的类的构造方法。n例:6.6clas
7、s car int color;float speed;car(int color)this.color=color;/构造方法I,this.color代表变量,color代表形参car(float speed)this(21);/引用构造方法I,必须是第一句。this.speed=speed;6.1.5 this和super关键字n2、super的用法n(1)表示他所在的类的直接父类。通过super可以访问父类中被子类中隐藏的变量和覆盖的方法。n例:6.7n(2)在子类中,用super调用父类的构造方法,初始化父类的成员变量。super语句要放在第一句。n例:6.86.1.4 this和su
8、per关键字nclass fathernint i,j,k;nString abc=I am father!;nfather(int i,int j)this.i=i;this.j=j;nnclass son extends fathernint c;nString abc=I am son!;nson(int a,int b,int c)nsuper(a,b);/super调用父类的构造方法,必须在第一句nk=23;nthis.c=c;nSystem.out.println(i=+i+nj=+j+nk=+k+nc=+c);nnvoid output()n System.out.println
9、(super.abc);/super代表直接父类,访问被隐藏的父类的变量。nn6.2 类的多态n6.2.1 方法的重载n含义:在同一个类中,以相同的名字定义多个方法,只是参数列表不同,即为方法的重载。n程序可以按参数决定调用对应的方法,此决定由编译器来做。即在调用时,Java将根据实参个数或参数类型选择匹配的方法。n例:6.106.2.2 构造方法的重载n即一个类中定义了多个构造方法,只是参数列表不同。实例化对象时,系统会根据传递参数的不同自动调用相应的构造方法。n详见5.2.3节。6.3 接口n6.3.1 接口的概念接口的概念n接口(界面):是用来组织应用中的各类并调节它们的相互关系的一种结
10、构,是用来实现类间多重继承的结构。n接口是一种特殊的类,它是方法定义(没有方法的实现)和常量值的集合。n多重继承:一个子类可以有一个以上的直接父类,该子类可继承它所有直接父类的成员。6.3.2 接口的声明接口的声明n接口声明格式:public interface 接口名 extends 父接口名列表/接口体public static final 域类型 常量名=常量值;/常量域声明,可为多个 public abstract native 返回值类型 方法名(参数列表)throws 异常列表;/抽象方法声明,可为多个6.3.2 接口的声明接口的声明n由接口声明的语法格式可以看出,接口是一种由常量
11、和抽象方法组成的特殊的类。Java中一个类只能有一个父类,但是它可以同时实现若干个接口,这种情况如果把接口理解为特殊类,则这个类利用接口实现了多重继承。n注:n(1)interface是定义接口的关键字。n(2)接口名只要符合Java对标识符的规定即可。n(3)接口的访问控制符只有一个public,用此修饰的接口为公共接口,可以被所有类和接口使用,否则只能被同一个包中的其他类和接口使用。6.3.2 接口的声明接口的声明n(4)接口具有继承性。定义一个接口时可通过extends声明该新接口是某个已存在的父接口的派生接口(子接口),它将继承父接口的所有属性和方法。与类不同的是一个接口可以有一个以上
12、的父接口,它们之间用”,”隔开,形成父接口列表。新接口将继承所有父接口中的属性和方法。如果在子接口中定义了和父接口同名的常量或方法,则父接口中的常量被隐藏,方法被重写。n(5)接口体的声明是定义接口的重要部分。接口体由两部分组成,一部分是对接口中属性的声明,另一部分是对接口中方法的声明。n(6)接口中的所有属性都必须是public static final修饰的,这是系统默认的规定。所以接口属性也可以没有任何修饰符,其效果完全相同。n(7)接口中的所有方法都必须是抽象方法。6.3.3 接口的实现n含义:为具体实现接口所规定的功能,则需要含义:为具体实现接口所规定的功能,则需要某个类为接口的抽象
13、方法书写语句并定义实在某个类为接口的抽象方法书写语句并定义实在的方法体,称为接口的实现。的方法体,称为接口的实现。n类要实现某个或某几个接口时的步骤和注意:类要实现某个或某几个接口时的步骤和注意:n(1)在类的声明部分,用)在类的声明部分,用implements关键字关键字声明该类将要实现哪些接口。声明该类将要实现哪些接口。n(2)如果实现某接口的类不是)如果实现某接口的类不是abstract类,类,则在类的定义部分必须要实现指定接口的所有则在类的定义部分必须要实现指定接口的所有抽象方法,即为所有抽象方法定义方法体,而抽象方法,即为所有抽象方法定义方法体,而且方法头部分应该与接口中的定义完全一
14、致,且方法头部分应该与接口中的定义完全一致,即有完全相同的返回值和参数列表。即有完全相同的返回值和参数列表。6.3.3 接口的实现n(3)如果实现某接口的类是抽象类,则它可以不实现)如果实现某接口的类是抽象类,则它可以不实现该接口所有的方法,但是对于这个抽象类任何一个非该接口所有的方法,但是对于这个抽象类任何一个非抽象的子类而言,它们父类所实现的接口中所有抽象抽象的子类而言,它们父类所实现的接口中所有抽象方法都必须有实在的方法体。这些方法体可以来自抽方法都必须有实在的方法体。这些方法体可以来自抽象的父类,也可以来自子类本身,但是不允许存在未象的父类,也可以来自子类本身,但是不允许存在未被实现的
15、接口方法。被实现的接口方法。n(4)一个类在实现某接口的抽象方法时,必须使用完一个类在实现某接口的抽象方法时,必须使用完全相同的方法头。如果所实现的方法与抽象方法有相全相同的方法头。如果所实现的方法与抽象方法有相同的方法名和不同的参数列表,则只是一个新的方法,同的方法名和不同的参数列表,则只是一个新的方法,而不是实现已有的抽象方法。而不是实现已有的抽象方法。n(5)接口的抽象方法,其访问限制符都已指定是)接口的抽象方法,其访问限制符都已指定是public,所以类在实现方法时,必须显式地使用,所以类在实现方法时,必须显式地使用public修饰符,否则将被系统警告为缩小了接口定义修饰符,否则将被系
16、统警告为缩小了接口定义的方法和访问控制范围。的方法和访问控制范围。6.3.3 接口的实现在使用接口的类体中可以使用:在使用接口的类体中可以使用:n接口中定义的常量接口中定义的常量n必须实现接口中定义的所有方法。必须实现接口中定义的所有方法。n在类中实现接口所定义的方法时,方法的声明必须与在类中实现接口所定义的方法时,方法的声明必须与接口中所定义的完全一致。接口中所定义的完全一致。n接口可以作为一种引用类型来使用,所以可以象其它接口可以作为一种引用类型来使用,所以可以象其它类型的一样使用。类型的一样使用。例:假如Sleeper 是接口 private Sleeper sleepers=new S
17、leeperMAX_CAPACITY;关于接口的两个问题讨论:关于接口的两个问题讨论:i i:接口是否能看成多重继承呢?接口是否能看成多重继承呢?接口虽然能完成多重继承的相似功能,但是完全不同的:n一个类仅仅继承接口中的常量。n一个类不能继承接口中的方法。n接口继承独立于类的继承。执行相同接口的类,不一定在类继承上相关。ii:ii:接口的用处主要体现在哪几个方面?接口的用处主要体现在哪几个方面?n通过接口可以实现不相关类的相同行为,而不需要考虑这些类之间的层次关系。n通过接口可以声明多个类需要实现的方法。n通过接口可以了解对象的交互界面,而不需了解对象所对应的类。6.4 包n定义定义:包是一组
18、相关的类或接口的集合,它提供了访问保护和名字空间管理。Java编译器使用文件系统目录来保存包。n使用包的好处:使用包的好处:1.程序员能很容易确定同一包中的类是相互关联的。2.程序员能很方便地了解到在哪里可以找到能完成特定功能的类.3.由于每个包都创建了一个名字空间,个人创建的类名不会和其它包中的类名名发生冲突.4.可以使同一包中的类彼此不加限制地访问,而同时对其它包中的类提供访问控制。6.4.1 包的创建1.创建包创建包格式:格式:package 包名1.包名2.包名3;package语句必须放在源文件的开始处,第一条语句。例如: java.io java.util java.lang ja
19、va.applet javax.swingpackage graphics;public class Circle.6.4.1 包的创建说明:说明:npackage的作用域是整个源文件;n如果在同一个源文件中定义了多个类,最多仅可以有一个类用public修饰,且源文件名必须与该类名相同;n当未使用package语句时,类和接口放在无名缺省包里;n包的命名习惯:将Internet域名作为包名。例如:pany.region.package.6.4.2 包的引用1.包的使用:使用长名字引用包中的公共包的使用:使用长名字引用包中的公共成员,即在类名前注明包名。成员,即在类名前注明包名。n要引用其他包中
20、类的成员,需要在类名前再要引用其他包中类的成员,需要在类名前再加上包名前缀。包名前缀加上包名前缀。包名前缀.类名前缀类名前缀.成员名成员名;n例:java.awt/包名.类名java.awt.Label mc1=new java.awt.Label();n注:包中的所有类中只有public类能被包外部的类访问。2.包的导入n用import关键字来导入一个包,使得该包的某些类或所有类能被直接使用。在Java源程序中,如果有package语句,则import语句紧接在其后,否则import语句应放在程序首行。nimport语句有三种形式:1)格式:格式:import 包名;包名;/这种形式允许使用
21、只用包名的最后一部分来指定包名。n例:如:import java.awt;/这条语句指定这个包中的文件存储在目录 path/java/awt下,包层次的根目录path是由环境变量CLASSPATH来确定的。n 则:awt.Label mc1=new awt.Label();6.4.2 包的引用2)格式:格式:import 包名包名.类名类名;例:如:import java.awt.Label;则:Label mc1=new Label();3)使用import语句引进包中的所有类和接口 格式:import 包名.*;n例:如:import java.awt.*;则:Label mc1=new
22、Label();n注:这种形式使得该包中所有类都可以直接用类名注:这种形式使得该包中所有类都可以直接用类名来访问,但同时会浪费内存的开销。来访问,但同时会浪费内存的开销。package com.bruceeckel.util;/*文件都置于自己系统的一个子目录中:C:DOCJavaTcombruceeckelutil */public class Vector public Vector()System.out.println(com.bruceeckel.util.Vector);/*需预先设置环境变量classpath:CLASSPATH=.;D:JAVALIB;C:DOCJavaT */
23、package c05;import com.bruceeckel.util.*;/另外包中的类用Vector 类:public class LibTest public static void main(String args)Vector v=new Vector();3.源文件和类文件的管理源文件和类文件的管理nJDK利用文件系统的层次结构来管理源文件和类文件。源文件和类文件所在的目录名应与其中的类所在的包名对应,编译器和解释器按此机制来查找类。如:3.源文件和类文件的管理源文件和类文件的管理n当源文件中有多个类定义时,编译后将产生多个类文件。3.源文件和类文件的管理源文件和类文件的管理
24、n虽然类文件所在的目录序列必须与包名对应,但不一定与源文件在相同的目录中。javac d d:classes Rectangle.java3.源文件和类文件的管理源文件和类文件的管理说明:说明:n包对应于文件系统的目录管理方式可以帮助编译器和解释器找到程序中的类和接口存放的地方。nCLASSPATH指出用户的类库所在目录,在类路径(CLASSPATH)中只需指出包路径之上的顶层路径CLASSPATH=.;d:classesn设置类路径的方法设置类路径的方法1.设置环境变量CLASSPATH(不推荐)set classpath=.;d:classes2.在调用编译器或解释器时使用-classpa
25、th选项 例 java-classpath d:classes com.taranis.grathpics.Test类成员的访问控制类成员的访问控制限访问修饰符关键字限访问修饰符关键字同一个类中同一个类中同一个包中同一个包中不同包不同包子类中子类中其他包其他包其他类中其他类中publicprotected无访问修饰符关键字无访问修饰符关键字(friendly-package)private6.5 Java的类库n6.5.1 Java类库简介-当前版本1.6。nJava系统事先设计并实现了一些体现了常用功能的标准类。这些系统标准类根据实现的功能不同,可划分为不同的集合,每个集合是一个包,合称为类
26、库类库。n一个用户程序中系统标准类使用得越多、越全面、越准确,这个程序的质量就越高。nJava的标准类和类库类似于C语言的库函数,都是一种应用编程接口,简称为API(Application Program Interface),),是开发编程人员所必须了解和掌握的。n开发者的Java编程能力在相当程度上取决于他对java类库的熟悉程度。nJava的标准类和类库的详细内容见JDK文档。JDK_API_1_6_zh_CN.CHM。6.5.2 语言基础类库njava.lang包语言基础类库简介n1.Object类所有类的直接或间接父类,也是类库中所有类的父类。包含了所有Java类的公共属性。n2.数据类型类基本数据类型的变换和操作。n3.Math类数学函数类,提供了基本的数学运算。n例:6.136.5.3 Java常用工具类库njava.util包低级的实用工具类。如:日期类,堆栈类,随机数类,向量类,等等。n1.(Gregorian)Calendar:日历类。n2.Vector:动态分配对象列表。n3.Stack:先进先出的对象栈。n4.Dictionary:关键字和值的数据对存储的集合。