1、第第3章章 Java面向对象编程面向对象编程面向对象的软件开发和相应的面向对象的程序设计方法是当今计算机技术发展的重要成果和趋势之一。Java是一种完全面向对象的程序设计语言,它的所有数据类型和函数都封装在类中。Java所实现的封装、继承、多态性等面向对象的属性,降低了程序的复杂性,实现了代码的可重用性,提高了运行效率,使Java不依赖于机器的结构,具有平台无关性、分布式、可移植性、可重用性、健壮性、安全性等特点。3.1 面向对象程序设计基础3.2 类与对象3.3 成员变量和成员方法的定义与实现3.4 类的继承与多态3.5 包3.6 接口和内部类习题学习目标【学习目标【学习目标】了解面向对象编
2、程的基本理论和基本概念,掌握面向对象编程的基本方法,学习后能够编写体现 OOP风格的Java程序。【本章知识点【本章知识点】类和对象的概念面向对象的特性类变量和类方法的使用封装和修饰符的使用内部类的使用接口的使用包层次的理解和使用3.1 面向对象程序设计基础面向对象程序设计基础3.1.1 面向对象概述3.1.2 面向对象中的基本概念3.1.3 面向对象程序设计方法的优点3.1.1 面向对象概述面向对象概述早期计算机中运行的程序大都是为特定的硬件系统专门设计的,称为面向机器的程序。这类程序的运行速度和效率都很高,但是可读性和可移植性很差,随着软件开发规模的扩大,这类面向机器的程序逐渐被以C为代表
3、的面向过程的程序所取代。面向过程问题求解的核心组成是数据结构和算法。其中数据结构利用计算机的离散逻辑来量化表达需要解决的问题,而算法则研究如何快捷、高效地组织解决问题的具体过程。面向过程的程序设计是以具体的的解体过程为研究和实现的主体,可以精确、完备地描述具体的求解过程(这里的过程通常是指操作),但却不足以把一个包含了多个相互关联的过程的复杂系统表述清楚。面向对象的程序设计不仅关心孤立的单个过程,还关心包含这些过程的复杂系统,它能够使计算机逻辑来模拟描述系统本身,包括系统的组成、系统的各种可能状态,以及系统中可能产生的各种过程与过程引起的系统状态切换。3.1.2 面向对象中的基本概念面向对象中
4、的基本概念1类与对象对象的概念是面向对象技术的核心所在。实际生活中,我们每时每刻都与“对象”打交道,比如屋顶上的猫、学生用的课桌、老王的彩色电视机等,甚至我们自己本身也是一个对象。我们平时怎样称呼对象呢?我们会以这个对象分类的名称来称呼它,例如城市里有很多猫、大街上有很多车、我要去看电视等等,这里的猫、车、课桌、电视都只是对象的一种分类而已。在Java中,我们称之为类。面向对象技术中另一个重要概念就是类,类是模板也是蓝图,从类中构造一个对象,即创建了一个类的实例。类好比一个建材市场,其中有许多子类各种各样的装饰材料,而我们装修自己的房子就要选择我们需要的材料(为了建立我们自己的程序,我们必须选
5、择我们需要的类)。3.1.2 面向对象中的基本概念面向对象中的基本概念对象和类之间是什么关系呢?比如你要买一台电视机,这里的“电视机”只是个类的名称,而你买回家的是电视机的一个实例对象,而不是一个类。所以类是一个抽象的概念,而对象是看得到、听得见、摸得着的实例。在面向对象的程序设计中,将数据与对数据进行的操作合起来定义为类。类是用来定义一组对象共同具有的状态和行为的模板。类(Class)是一种复杂的数据类型,它是将数据和与数据相关的操作封装在一起的集合体。类是普通数据类型的扩展,它不但包含数据,还包含了对数据进行操作的方法(method)。方法反映的是数据的行为而不是数据本身。对象(Objec
6、t)是类的实例,它是类的变量。当程序运行时,对象占用内存单元。对象与类是密切相关的,没有脱离对象的类,也没有不依赖于类的对象。3.1.2 面向对象中的基本概念面向对象中的基本概念图3-1表示了类、对象、实体的相互关系和面向对象问题求解的思维方式。使用面向对象的方法解决现实世界的问题时,首先将物理存在的实体抽象成概念世界的抽象数据类型,这个抽象数据类型里面包括了实体中与需要解决的问题相关的数据和属性;然后再用面向对象的工具,如Java语言,将这个抽象数据类型用计算机逻辑表达出来,即构造计算机能够理解和处理的类;最后将类实例化就得到了现实世界实体的面向对象的映射对象,在程序中对对象进行操作,就可以
7、模拟现实世界中的实体上的问题并解决之。3.1.2 面向对象中的基本概念面向对象中的基本概念Java中的所有数据类型都是用类实现的,Java语言是建立在类这个逻辑结构之上的,所以Java是一种完全面向对象的程序设计语言,而我们编写Java程序,主要工作是编写一个个类,然后由类生成对象,实现所需要的功能。映射对象类实体抽象数据类 计算机逻辑的实现概念世界计算机世界现实世界 抽象实例化抽象图3-1 对象、实体与类3.1.2 面向对象中的基本概念面向对象中的基本概念2.成员在Java语言中,一切事物都是对象。实际上,对于每个对象都有一个抽象过程。所谓抽象,就是选取所描述事物在现实世界中相关特征的过程。
8、任何事物一定存在3类信息:属性信息:静态刻画对象特征。操作信息:动态刻画对象特征。约束信息:描述对象可以存在的状态为了使得计算机能够处理客观事物,必须对事物进行抽象。在事物抽象过程中,必须胡略那些抽象事物与当前目的无关的特征,只需要关注与当前需求有直接影响的因素。3.1.2 面向对象中的基本概念面向对象中的基本概念例如,“人”可以看作一个抽象的类,我们每一个人都是“人”类的一个实例对象。公安机关要了解某一个人的情况,目前所关注的属性有身份证号、姓名、性别、出生日期等。而身高、体重是目前不关心的信息,要尽量去掉,当然以后可以根据需要随时再增加进来。所以有了属性,世界上每个对象都不同,就算是双胞胎
9、,也有不同的地方。每个对象有自己的行为或方法,比如我们可以说“那个人在吃饭”,那么吃饭、走路、工作是描述该实例的行为;又比如每台电视都不同,但每台电视一定会有开关机、选台、音量调节等操作的方法,这些都属于操作信息。我们把属性和方法称为这个对象的成员。类中的数据称为成员字段(field),对数据进行的操作称为成员方法(method)。注意:注意:字段表示的是类的属性,在Java中其实就是个变量,可以按照一般变量声明的格式进行声明,所以在下文中将字段称为变量。3.1.2 面向对象中的基本概念面向对象中的基本概念3.类的三个核心特性:封装、继承、多态(1)封装封装(encapsulation),即信
10、息隐藏,是面向对象程序设计中一个非常重要的概念。封装的目的有:隐藏类的实现细节,以防别人误用。迫使用户通过接口去访问数据。增强代码的可维护性。类封装的概念可以用集成电路芯片作类比。一块集成电路芯片由陶瓷封装起来,其内部电路是不可见的,也是使用者不关心的。芯片的使用者只关心芯片的引脚的个数、引脚的电量参数以及引脚提供的功能,通过这些引脚,硬件工程师对这个芯片有了全面的了解。硬件工程师将不同芯片的引脚连在一起,就可以组成一个具有一定功能的产品。软件工程师通过使用类也可达到这个目的。3.1.2 面向对象中的基本概念面向对象中的基本概念(2)继承继承是一种由已有类创建新类的机制。为什么要使用继承技术呢
11、?在编写大型应用程序时,如果所定义的类已被使用,应如何增加程序的可维护性?既要保证程序修改后不影响使用,又要能够对程序功能进行不断的补充。有两种传统的解决办法:直接对原代码进行改动:可行,但会对现有使用的其它类造成影响。对原类定义进行复制,对复制的类进行改动,以支持新功能。此方法可行,但也会产生问题:在复制代码的同时,也会复制错误,使得程序的可移植性和重用性差,必然导致工作量的增加。这两种办法并不能最终解决问题,更好的解决办法是使用继承技术。继承机制提供了一种无限重复利用程序资源的途径。通过继承可以扩充旧的程序以适应新的需求,这样不仅节省程序开发时间,而且为未来程序设计增添了新的资源。3.1.
12、2 面向对象中的基本概念面向对象中的基本概念(3)多态一般来讲,多态就是多种形态的意思。我们已经知道,利用面向对象的语言编程,主要工作是编写一个个类,每一个类中可能有多个成员方法,这些方法各自对应一定的功能,它们之间是不能重名的,否则在用名字调用时,就会产生歧义和错误。但在实际编程过程中,有时却需要利用这样的“重名”现象来提高程序的抽象度和简洁性,这就体现了多态性。所谓多态,是指一个程序中使用相同名字的定义了不同的方法。多态性允许以统一的风格处理已存在的变量及相关的类。多态性使得向系统增加新功能变得容易。继承性和多态性是降低软件复杂性的有效技术。3.1.3 面向对象程序设计方法的优点面向对象程
13、序设计方法的优点相对于传统的面向过程的程序设计,面向过程的程序设计更符合人解决问题的思维习惯,它具有如下优点:1.对象的数据封装特性彻底消除了传统结构方法中数据与操作分离所带来的种种问题,提高了程序的可重用性和可维护性,降低了程序员保持数据与操作相容的负担。2.对象的数据封装特性还可以把对象的私有数据和公共数据分离开,保护了私有数据,减少了可能的模块间干扰,达到降低程序复杂性、提高可控制性的目的。3.通过继承和多态,可以很方便地实现应用的扩展和已有代码的重复使用,在保证质量的前提下提高了开发效率,减小软件修改的难度。3.2 类与对象类与对象3.2.1 类的声明、类体3.2.2 创建对象与构造方
14、法3.2.1 类的声明、类体类的声明、类体成员变量的声明格式:staticfinaltransient;其中,方括号中的项都是可选的。各项的含义如下:static指明变量是一个类成员变量。final指明变量是常量。transient指明变量是临时变量。如:例3.53.2.2 创建对象与构造方法创建对象与构造方法类的行为由它的方法实现,其他对象可以调用对象的方法来得到该对象的服务。方法的声明与实现也可分为两部分:方法声明和方法体。成员方法的声明格式:修饰符 (参数列表)throws 如:例3.6 3.3.3 类的封装类的封装前面我们设计的所有Person类,其中age属性是其他所有类都能直接使用
15、或是修改的,这样的使用方式虽然很直接也很简单,不过有一个很严重的问题。age属性是一个int类型的变量,它的取值范围很大,你可以把它设为-12,也可以把它设为10000,可是世界上没有一个人的年龄为负数,也没有一个人活了10000岁。所以我们必须保护这种属性,防止别人乱用。保护的方式就是把属性隐藏起来,使得其他类只有通过特定的方法才能使用、修改这些属性。在面向对象程序设计中,信息的隐藏就是封装(encapsulation)。封装的目的有:隐藏类的实现细节,保护类中的数据不被误用或破坏。迫使用户通过接口去访问数据。增强代码的可维护性。3.3.3 类的封装类的封装那么,如何封装呢?根据封装原则,使
16、用者可以访问类中的部分方法,但不能直接访问成员变量。Java中通过设置类的访问权限和类中成员的访问权限,来实现封装的特性。在声明一个类时,可以不用权限修饰符,也可以用public设置类为公有的,不允许使用其他的权限修饰符。对于类中成员的访问权限,Java定义了4种访问权限:公有的(public)、保护的(protected)、默认(default)的和私有的(private)。表3-1说明了每一种权限修饰符允许的访问级别。3.3.3 类的封装类的封装权限修饰符同一类同一包不同包的子类所有类公有的(public)保护的(protected)默认的(default)私有的(private)表3-1
17、 权限修饰符允许的访问级别3.3.3 类的封装类的封装当设置类成员的访问权限时,4种修饰方式的含义如下:公有的(public):说明该类成员可被所有类的对象使用。保护的(protected):说明该类成员能被同一类中的其他成员、或其子类成员、或同一包中的其他类访问,不能被其他包的非子类访问。默认的(default):其实并没有一个叫default的修饰符,如果在声明一个成员时,成员前面没有加上其他三种修饰符,就叫default。它的限制比protected还严格,它使得该类成员能被同一类中的其他成员、或同一包中的其他类访问,但不能被其他包的类访问。私有的(private):说明该类成员只能被同
18、一类中的其他成员访问,不能被其他类的成员访问,也不能被子类成员访问。成员方法和成员变量都是Java类的成员。当声明一个类的成员时,可以使用权限修饰符允许或不允许其他类的对象访问其成员。如:例3.73.3.3 类的封装类的封装类型初值类型初值byte0float0.0fshort0double0.0int0charu0000long0booleanfalse引用类型null表3-2 Java各种类型变量的初值3.3.4 实例成员和类成员实例成员和类成员以前我们看到的属性或是方法,都是属于对象等级的,它们是伴随对象的,也就是说只有当对象实例化以后,那些属性和方法才有存在的意义,因此我们称这些属性或
19、方法为实例成员。学校里人很多,为了方便管理,所以我们必须统计出人的总数。有些属性和方法不需要伴随对象,例如学校的总人数,如果我们把它交由上层的类来管理,会比较容易而且效率更高,我们称这种属性或方法为类成员。Java类就包括两种成员:实例成员和类成员。类成员也称为静态成员。使用static修饰的成员称为类成员。3.3.4 实例成员和类成员实例成员和类成员1.实例变量和类变量类的成员变量有实例变量和类变量两种。没有static修饰的变量称为实例变量,每次创建类的一个实例对象时,系统会为对象的每一个实例变量分配内存单元。用static修饰的变量称为类变量或静态变量,系统运行时,只为该类的第一个对象分
20、配内存单元,其后所有新创建的对象都共享这一个类变量。2.实例方法和类方法类的成员变量有实例方法和类方法两种。没有static修饰的方法称为实例方法。实例方法体中既可以访问类变量,也可以访问实例变量。实例方法只能通过对象来调用。用static修饰的方法称为类方法或静态方法。类方法体中只能访问类变量。类方法既可以通过对象来调用,也可以通过类名调用。如:例3.83.3.4 实例成员和类成员实例成员和类成员注释:注释:许多面向对象语言(如C+)要求程序跟踪所以创建的对象,在对象使用完后显式地销毁对象,用这种方式编写管理内存的代码既麻烦有容易出错。而在Java中,程序员只需创建对象,不需要显式地销毁它们
21、。因为Java有垃圾回收机制,能自动判断对象是否在使用,如果不使用,则自动销毁它,收回对象所占的资源。在程序中也可以使用析构方法finalize()随时销毁对象。Java的每个类都有一个析构方法,用于将资源返回给系统。方法finalize()没有参数,也不返回值。3.4 类的继承与多态类的继承与多态3.4.1 类的继承3.4.2 类的多态3.4.3 最终类和抽象类3.4.1 类的继承类的继承1继承的概念根据不同的职业,人可以分为警察、演员等不同的类别。光靠一个Person类来包括各种职业的属性和方法,其结构性是很差的。所以我们必须设计新的类,来管理不同职业的人。所谓继承(inheritance
22、),就是一种由已有类创建新类的机制。利用继承,我们可以先创建一个具有公共属性的一般类,然后根据该一般类再创建具有特殊属性的新类。新类继承一般类的属性和方法,并根据需要增加它自己的属性和方法。由继承而得到的新类称为子类(subclass),被继承的类称为超类(supclass),也被称为父类。3.4.1 类的继承类的继承例如,当类sub1继承类super时,就表明sub1是super的子类,super是sub1的超类,如图3-2所示。子类从超类中继承变量和方法,从而可以共享数据和方法。Sub1类由两部分组成:继承部分和增加部分。继承部分是从super继承过来的,把super的成员映射成sub1的
23、继承成员;增加部分是专为sub1编写的新代码。如:例3.9图3-2 继承性注意:注意:Java不支持多重继承,即子类只能有一个超类。3.4.1 类的继承类的继承2创建子类实现继承创建子类实现继承在类的声明中,通过使用关键字entends来创建一个类的子类,显式声明格式为:class extends 例如,class Student extends Person3.4.1 类的继承类的继承子类继承超类中所有可被子类访问的成员变量。继承原则如下:能够继承声明为public和protected的成员变量。能够继承同一包中的那些默认修饰符的成员变量。不能继承声明为private的成员变量。如果子类声明
24、一个与超类成员变量同名的成员变量,则不能继承超类的成员变量。此时,子类的成员变量称为隐藏了超类的成员变量。子类继承方法的规则类似于继承成员变量的规则:子类继承超类中所有可被子类访问的成员方法。继承原则如下:能够继承声明为public和protected的成员方法。能够继承同一包中的那些默认修饰符的成员方法。不能继承声明为private的成员方法。不能继承超类的构造方法。如果子类方法与超类方法同名,则不能继承。子类方法称为覆盖了超类的同名方法。3.4.1 类的继承类的继承注意:注意:Java中每个类都有超类,如果没有显式标明类的超类,则隐含地假设超类为在语言包java.lang中说明的Objec
25、t类。如:例 3.10 3.4.1 类的继承类的继承归纳注释:归纳注释:继承是软件重用的一种形式,也是自动地实现类中方法和数据共享的机制。如果没有继承机制,那么一个系统中的类是封闭的、相互无关的。多个类实现相似的功能势必造成数据和方法的大量重复。而有了继承机制,多个类就可以相互关联,新类从已存在的类中产生,通过保留它们的属性和方法实现代码重用,又可以根据新类的要求添加新的属性和方法,以支持新功能。在编写大型应用程序时,软件重用可大大缩短软件开发时间,提高系统性能,减少系统在使用过程中出现的问题。3.4.2 类的多态类的多态所谓多态(polymorphism),是指一个名字可具有多种语义,即“同
26、名异示”。例如,我们经常说,“哺乳动物有很多种叫声”,描述为“吼”、“嚎”、“汪汪”、“喵喵”等,这就是叫声的多态。如何实现叫声的多态呢?我们写动物类时,写了“叫声”方法,动物类有很多子类,并且这些子类都重写了超类中的“叫声”方法,会产生不同的行为。比如,狗类对象调用“叫声”方法时,产生的行为是“汪汪”,而猫类对象调用“叫声”方法时,产生的行为是“喵喵”。这就实现了叫声的多态。多态性允许以统一的风格处理已存在的变量及相关的类。多态性使得向系统增加新功能变得容易。继承和多态是降低软件复杂性的有效技术。通常有两种途径实现多态:方法的重载和覆盖。3.4.1 类的继承类的继承1方法的重载所谓方法的重载
27、(method overloading),是指一个类中有许多同名的方法带有不同的参数表。方法重载时,要求:参数必须不同,即可以是参数个数不同,也可以是个数相同而类型不同。返回值可以相同,也可以不同。例如,输出语句print的参数可以是Java中的任何基本类型,其实就是对print()方法的重载:public void print(boolean b)public void print(char c)public void print(int i)public void print(long l)public void print(float f)public void print(double
28、 d)例 3.11 构造方法的重载3.4.1 类的继承类的继承归纳注释:归纳注释:重载的价值在于它允许通过使用一个普通的方法名来访问一系列相关的方法。当调用一个方法时,具体执行哪一个方法要根据调用方法的参数决定,Java运行系统仅执行与调用的参数相匹配的重载方法。尽管Java并没有规定重载方法之间必须有联系,但习惯上,为了使程序容易读懂,最好重载相同含义的方法。3.4.1 类的继承类的继承2方法的覆盖在有继承关系的两个类中,如果子类方法与超类方法同名,则该方法不能继承,此时子类的方法称为覆盖(override)了超类中的同名方法。例如,在例3.10中,三个子类Student_i、Profess
29、or_i、Assistant_i类都继承超类Person_i,子类中都重写work方法覆盖了超类中的同名方法,各个子类的work方法彼此不同,都实现了与超类不同的行为。特别是在程序中第80行,子类Assistant_i中重写work方法覆盖了超类中的同名方法,在89行子类对象a调用的work方法是子类的,所以输出了语句“Talking with a student”,而不是超类的work方法中要输出的“Working.”。所以,方法的覆盖与类的继承有密切的关系。覆盖体现了子类补充或改变超类方法的能力。通过覆盖使一个方法在不同的子类间表现出不同的行为。3.4.1 类的继承类的继承在进行覆盖时,应
30、注意以下三点:子类不能覆盖超类中声明为final或static的方法。子类必须覆盖超类中声明为abstract的方法,或者子类也声明为abstract。子类覆盖超类中同名方法时,子类方法声明必须与超类被覆盖方法的声明一样。3.4.3 最终类和抽象类最终类和抽象类1最终类最终类是指不能被继承的类,即:最终类不能有子类。如果不希望某个类被继承,可以用关键字final来声明这个类为最终类。例如:final class C /合法,C为最终类class Lx extends C /非法,Lx不能为最终类的子类如果想保护类中的方法不被子类覆盖,可以在声明中用关键字final来声明这个方法为最终方法。例如
31、:final void m();/合法,m为最终方法2抽象类为了确保一个方法能被子类的方法覆盖,则使用关键字abstract声明该方法为抽象方法。例如:3.4.3 最终类和抽象类最终类和抽象类abstract class D /合法,D为抽象类class Lx extends D /合法,Lx可以为抽象类的子类D d=new D()/非法,抽象类不能实例化抽象类的子类必须实现超类中的所以抽象方法,或者将自己也声明为抽象的。一个类不能既是最终类,又是抽象类,即:关键字final和abstract不能合用。当我们定义一个抽象概念时,可以声明一个抽象类只描述其中的结构,而不实现每个方法。这个抽象类可
32、以作为一个超类被它的所有子类所共享,而其中的方法由每个子类去实现具体细节。3.5 包包3.5.1 包的概念3.5.2 引用Java定义的包3.5.1 包的概念包的概念Java允许使用包(package)把类聚集起来。所以包是一种区别类名空间的机制,是类的组织方式,包对应一个文件夹,包中还可以再有子包,称为包等级。为什么要使用包呢?假设有两个程序员不约而同地提供了Student类,只要他们把自己的类放入不同的包中,那么就不会产生冲突。对于其中不同的项目,则使用子包进行区分。包等级的唯一目的是要管理唯一的名字。从编译器的角度来看,包和其中的子包没有任何关系。例如,包java.util和java.u
33、til.jar就是彼此无关的,它们每一个都有自己独立的类集合。3.5.2 引用引用Java定义的包定义的包在本书第1章有关Java的API结构的内容中,对Java的常用包作了简单介绍,在此不再赘述。为能使用其他包中的类(或接口),在Java语言中提供了一个包可以使用另一个包中类(或接口)的定义和实现的机制。在一个包中的类共有两种方式定义来自其他包中的类(或接口)。1前缀包名法在每个欲引用的类(或接口)名前简单加上完整的包名。例如,java.util.Date today=new java.util.Date();显然,这样太繁琐。3.5.2 引用引用Java定义的包定义的包2使用import关
34、键词在源程序中使用import语句导入Java包中的一个类(或接口),或者包含它们的包。导入一个包后,该包所有的公用类和接口均可使用。import语句的格式 为:import.|*;其中import为关键字,多个包名及类名之间用圆点分隔,“*”表示包中的所有类。import语句可以有多个,但必须都在文件顶部package语句后,并且在文件中第一个类或接口定义之前。例如,先有语句import java.util.*;然后,可以直接使用下面的语句:Date today=new Date();如果存在名字冲突,必须使用前缀包名法。例如:import java.util.*;import java.s
35、ql.*;/其他语句Date today=new Date();3.5.2 引用引用Java定义的包定义的包该程序在编译时会报错,因为java.util包和java.sql包中都有Date类,编译器无法确定用哪一个类创建对象today。改为下面的代码就可编译通过:import java.util.*;import java.sql.*;java.util.Date today=new java.util.Date();java.sql.Date yesterday=new java.sql.Date();3设置包的路径要引用Java包,仅在源码中增加import语句是不够的,还必须告诉系统,程
36、序运行时到哪里才能找到Java的包。这个功能由环境变量classpath完成。在本书第1章JDK的安装过程中已经有关于如何设置环境变量classpath的内容:set classpath=.;C:Program FilesJavajdk1.5.0_07lib如:例 3.12 3.5.3 自定义包自定义包除了可以引用Java定义的包之外,程序员还可以定义自己的包。1包的定义格式(1)包的定义格式如下:Package;其中,package是关键字,是标示符。例如:Package school;Public class Person_i;(2)包等级的定义格式如下:Package.;用圆点“.”将每
37、个包名分隔就能形成包等级,而包等级中的包名称说明Java类的命名空间的目录层次。例如:Package school.one.two;同时要求one是school的子文件夹,而two是one的子文件夹。要注意的是,如果改变某一个包名,必须同时改变对应的文件夹名。因为包的名字与类存放的文件夹同名。3.5.3 自定义包自定义包2.设置包的路径对于程序员自定义的包school,系统如何知道这个包在哪里?其他类如何引用他?我们在D:myjava之中创建一个与包同名的文件夹D:myjavaschool,并将编译过的文件(Person_i.class)放入该文件夹中。注意:该包名与文件夹名应该一致。添加环境
38、变量classpath的路径如下:set classpath=.;C:jdk1.3.0_02lib;D:myjava其他类用import school.*;语句可以引用school包中的类。程序运行时,系统将在D:myjava中寻找school包。JVM在定位一个Java类文件时分为两个步骤:外部定位:根据classpath环境变量定位查找Java类的起始位置。内部定位:根据每个Java类中package关键字所定义层次在Java命名空间中进行再定位。3.5.3 自定义包自定义包例3.13 包等级的创建及使用。按照下列目录结构,改写例3.9和例3.10中的4个类Person_i、Student
39、_i、Professor_i、Assistant_i,把类添加到相应的包中。设计一个信息系学生的新类Is,使之继承Student_i类,并在Is中创建包中所有类的对象且调用各个类的move方法。目录结构为:D:myjavaschool Person_i.java management Assistant_i.java Assistant_i.class student Student_i.java Student_i.class Is.java Is.class teacher Professor_i.java Professor_i.class3.5.3 自定义包自定义包(1)设置class
40、pathset classpath=.;C:Program FilesJavajdk1.5.0lib;D:myjava(2)修改并编译原有的四个类首先,需要在D:myjava中创建三个子文件夹,名字分别为management、student、teacher;其次,将Person_i.java拷入文件夹myjava中;然后再将Student_i.java中的三个类的源代码分开写成三个类文件,将Assistant_i.java拷入management文件夹中,将Student_i.java拷入student文件夹中,将Professor_i.java拷入teacher文件夹中,最后依次改写这四个程
41、序并编译为字节码文件。3.5.3 自定义包自定义包Person_i.java程序改为:1.package school;2./*3.文件:Person_i.java4.说明:Java实用教程例3.135.*/6.public class Person_i7.8./类体的代码与例3.9中一样9.使用下面的编译命令,可将Person_i.java编译为Person_i.class文件。D:myjavaschooljavac Person_i.java3.5.3 自定义包自定义包Student_i.java程序改为:1.package school.student;/把Student_i类放入包sc
42、hool的子包student中2./*3.文件:Student_i.java4.说明:Java实用教程例3.135.*/6.import school.Person_i;/由于Student_i类要继承超类Person_i,所以需要先导入该类7./子类Student_i,继承超类Person_i8.public class Student_i extends Person_i9.10.protected String dept;/子类变量11.static private int count=0;3.5.3 自定义包自定义包12.public Student_i(String n,int a,
43、String d)13.14.super(n,a);15.dept=d;16.setKind(Student);/调用从超类继承的方法17.count+;18.19.public static int getCount()20.21.return count;22.23.public void work()24.25.System.out.println(Having classes);26.27.3.5.3 自定义包自定义包使用下面的两种编译命令,都可将Student_i.java编译为Student_i.class文件。D:myjavaschoolstudentjavac Student_
44、i.javaD:javac D:myjavaschoolstudentStudent_i.javaAssistant_i.java程序改为:1.package school.management;/把Assistant_i类放入包school的子包management中2./*3.文件:Assistant_i.java4.说明:Java实用教程例3.135.*/6.import school.Person_i;7./子类Assistant_i,继承超类Person_i3.5.3 自定义包自定义包8.public class Assistant_i extends Person_i9.10.pr
45、otected String dept;11.static private int count=0;12.public Assistant_i(String n,int a,String d)13.14.super(n,a);15.dept=d;16.setKind(Assistant);17.count+;18.19.public static int getCount()20.21.return count;22.3.5.3 自定义包自定义包23.public void work()24.25.System.out.println(Talking with a student);26.27
46、.public void sub_print()28.29.super.work();30.System.out.println(子类对象的个数:this.count=+this.getCount();31.System.out.println(超类对象的个数:super.count=+super.getCount();32.33.如上例所示,使用两种方法,都可将Assistant_i.java编译为Assistant_i.class文件。D:javac D:myjavaschoolmanagementAssistant_i.java3.5.3 自定义包自定义包Professor_i.java
47、程序改为:1.package school.teacher;/把Professor_i类放入包school的子包teacher中2./*3.文件:Professor_i.java4.说明:Java实用教程例3.135.*/6.import school.Person_i;7./子类Professor_i,继承超类Person_i8.public class Professor_i extends Person_i9.10.protected String dept;11.static private int count=0;12.3.5.3 自定义包自定义包13.public Professo
48、r_i(String n,int a,String d)14.15.super(n,a);16.dept=d;17.setKind(Professor);18.count+;19.20.public static int getCount()21.22.return count;23.24.public void work()25.26.System.out.println(Teaching);27.28.3.5.3 自定义包自定义包我们使用下面的语句将Professor_i.java编译为Professor_i.class文件。D:javac D:myjavaschoolteacherPro
49、fessor_i.java(3)编写信息系学生的新类Is程序代码为:1.package school.student;/把Is类放入包school的子包student中2./*3.文件:Is.java4.说明:Java实用教程例3.135.*/6./由于本类中要调用Person_i等四个类,所以需要先导入7.import school.Person_i;8.import school.student.*;3.5.3 自定义包自定义包9.import school.teacher.*;10.import school.management.*;11./子类Is,继承超类Student_i12.p
50、ublic class Is extends Student_i13.14.static private int count=0;15.public Is(String n,int a)16.17.super(n,a,信息系);/调用超类的构造方法18.setKind(Student of Information Department);19.count+;20.21.public static int getCount()22.23.return count;24.3.5.3 自定义包自定义包public void work()System.out.println(Programming.)