JAVA语言项目3JAVA面向对象编程.ppt
面向对象程序设计(Object Oriented Programming)简称(OOP),是一种新兴的程序设计方法,其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计。类是Java程序中的最基本构件,即Java程序是一大堆类的集合。,下一页,项目3 Java面向对象编程,项目3 Java面向对象编程,3.1 项目概述3.2 项目目的3.3 项目支撑知识3.4 项目实施3.5 项目总结3.6 扩展训练,3.1 项目概述,在本项目中主要学习面向对象程序设计的基本思想和面向对象的概念,类的定义,成员变量和成员方法的定义及使用,对象的创建和使用,类的继承和多态,访问控制和修饰符,抽象类、接口和包的声明及实现方法。,返回,3.2 项目目的,掌握创建和使用类对象、使用包的基本方法。.理解继承和复用的概念。.了解接口的声明及实现方法。.理解多态性是如何扩充和维护系统性能。,返回,3.3 项目支撑知识,面向对象是一种新兴的程序设计方法,或者是一种新的程序设计规范(paradigm),其基本思想是使用对象、类、继承、封装、消息等基本概念来进行程序设计。从现实世界中客观存在的事物(即对象)出发来构造软件系统,并且在系统构造中尽可能运用人类的自然思维方式。开发一个软件是为了解决某些问题,这些问题所涉及的业务范围称作该软件的问题域。其应用领域不仅仅是软件,还有计算机体系结构和人工智能等。在面向过程的设计中,程序员只限于使用语句构建软件,即把语句集合起来组成方法(后面称之为函数或过程)。,下一页,返回,3.3 项目支撑知识,如建筑师,只限于使用木、水、土等原材料搭建房屋,工作多,效率低。并且在房子需重新翻盖时,所有的原材料将没有用。但如果将水、土先烧成砖,木先制成门、窗等,盖房时使用砖、门、窗成形的原料,只需考虑不同型号的门、窗放的位置。即使已建成的房屋,需要重新翻盖,也不用从零开始,砖、门、窗等原材料都可重新再用,可提高工作效率,降低成本。这一类工程设计类似于面向对象的程序开发。,上一页,下一页,返回,3.3 项目支撑知识,项目开发背景知识 1面向对象的概述一、面向对象的基本概念1.对象的基本概念对象是代表现实生活中的实物的软件编程实体,比如说银行账号,计算机用户,用户介面上的按钮,窗口菜单等。对象是由它们的状态和行为定义的。例如,一个银行账号拥有一种状态,诸如当前的收支状况,账户的所有入,允许的最小交易额等,而它的行为则包括提取,存入,收支平衡等。,上一页,下一页,返回,3.3 项目支撑知识,对象具有两方面的含义:在现实世界中,是客观世界中的一个实体;在计算机世界中,作为真实世界的抽象,由一个数据集以及对该数据集的操作组成。2.类的基本概念类:具有共同属性和行为的对象集合。类与对象的关系:类是对象的抽象,对象是类的实例。类是一个实体,它定义了一个对象的运行方式以及在对象被创建或者说实例化的时候所包含的数据。类的作用就像一个模板,一个或者多个对象可以依照它来创建。,上一页,下一页,返回,3.3 项目支撑知识,3.消息消息:对象之间相互请求或相互协作的途径,是要求某个对象执行某项功能操作的规格说明。消息内容:通常包含接收方及请求接收方完成的功能信息。发送方:发出消息,请求接收方响应。接收方:收到消息后,经过解释,激活方法,予以响应。消息的性质:同一对象可接收不同形式的多个消息,产生不同的响应。同一个消息可以发给不同的对象,所做出的响应可以截然不同;发送方不需要知道接收方如何对请求予以响应的。,上一页,下一页,返回,3.3 项目支撑知识,消息就是向对象发出的服务请求,它应该包含下述信息:提供服务的对象标识、服务标识、输入信息和回答信息。服务通常被称为方法或函数。举例说明:对象是具有某种特性和某种功能的东西。将同一种类型的对象归为一个类,以类的形式描述对象的状态和功能。例如,汽车是一类,其中如小轿车、中型面包车、大货车等,可认为是对象。类是对象的抽象,对象是类的实例。那么汽车就是Java中的类,判定某一对象是否是汽车,要看它是否具有这些属性,而自行车不能叫汽车,因为它不具有发动机属性。,上一页,下一页,返回,3.3 项目支撑知识,在面向对象的程序设计中,将类的特征和行为分别命名为属性和方法。例如,定义“电视机”这样一个类,如图3-1所示。电视机的属性和方法定义如图3-2所示。一个类中定义的方法可以被该类的对象调用,对象方法的每一调用被称作发送一个消息(message)给对象。对象间是相互独立的,通过发送消息相互影响。采用消息可以让对象的行为通过它的方法来表达。一个消息由三部分组成:消息目标对象;执行方法的名字;,上一页,下一页,返回,3.3 项目支撑知识,执行方法所需要的参数(parameters)。(因Java是一个对象化的语言,对象也常被用来当作参数传递)。方法。表明对象所具有的行为,是对象与外界的接口。一个对象的行为是由它上面的操作定义的,这些操作被叫做方法。方法可以改变一个对象的状态,创建新对象,实现实用的功能等。作用:改变对象的属性,返回对象的属性。二、面向对象的特点,上一页,下一页,返回,3.3 项目支撑知识,(1)封装。隐藏实现细节。例如,对象可以看作是数据及作用在这些数据上的封装体,它通过一个接口与外部进行交互,因此封装使得对象的内部实现与外部接口分离开来。这样,改变对象的内部实现并不影响使用这个对象的其他对象或应用。这种封装性也体现了一种抽象和信息隐蔽。(2)继承性。继承是指一个子类继承父类(或称为基类)的特征(数据结构和方法)。在继承一个父类时,可以在子类中增加新的数据结构和方法,也可以重定义从父类中继承下来的方法。父类的特征并不受子类的影响,反之,在理想情况下,父类的内部实现的变化不会影响子类。,上一页,下一页,返回,3.3 项目支撑知识,当然,一个子类可有多个父类,这种情况称为多继承(C+语言支持多继承)。继承带来的好处是软件的复用,使用继承可以在已有软件构件的基础上构造新的软件,从而提高软件的生产率并保证软件的质量。简而言之,继承性是父类和子类之间共享数据和方法的机制;继承性具有传递性;继承性包括单继承和多重继承。继承性具有以下作用:使软件系统具有开放性;更好地进行抽象与分类;增强代码的重用率;提高可维护性。,上一页,下一页,返回,3.3 项目支撑知识,(3)多态性。不同的对象收到同一个消息可产生完全不同的效果,这一现象叫做多态。多态的原意是指一个实体多个形态。在面向对象程序设计中主要是指变量多态和方法多态,变量多态是指同一个变量在运行时刻标识(表示)不同类型的对象,而方法多态主要是指同一个方法做不一样的动作,例如不同类的对象接受相同的消息(方法调用),但有不一样的响应动作。多态使得消息发送者能给一组具有公共接口的对象发送相同的消息,接收者作出相应的动作。变量多态是方法多态的基础。多态通常与语言的动态绑定(Dynamic Binding)机制有关。,上一页,下一页,返回,3.3 项目支撑知识,多态的效果:用户发送一个通用的消息,而实现的细节则由接收对象自行决定。多态性的作用:增强了操作的透明性、可理解性和可扩展性;增强了软件的灵活性和重用性。三、面向对象的优点为什么现代程序设计语言会向面向对象编程靠拢?这是因为面向对象编程具备了几个优点,比如:代码维护方便、可扩展性好、支持代码重用技术等。这些优点是过程编程语言所不具备的。下面我们就来谈谈面向对象技术的这些优点。,上一页,下一页,返回,3.3 项目支撑知识,(1)维护简单。模块化是面向对象编程中的一个特征。实体被表示为类和同一名字空间中具有相同功能的类,可以在名字空间中添加一个类而不会影响该名字空间的其他成员。(2)可扩充性。面向对象编程从本质上支持扩充性。如果有一个具有某种功能的类,就可以很快地扩充这个类,创建一个具有扩充的功能的类。(3)代码重用。,上一页,下一页,返回,3.2 项目支撑知识,由于功能是被封装在类中的,并且类是作为一个独立实体而存在的,提供一个类库就非常简单了。事实上,任何一个编程语言的程序员都可以使用类库,类库提供了很多的功能。更令人高兴的是,可以通过提供符合需求的类来扩充这些功能。项目开发背景知识 2类的定义进行Java程序设计,实际上就是定义类的过程。一个Java源程序文件往往是由许多个类组成的。从用户的角度看,Java源程序中的类分为两种。,上一页,下一页,返回,3.3 项目支撑知识,(1)系统定义的类,即Java类库,它是系统定义好的类。类库是Java语言的重要组成部分。Java语言由语法规则和类库两部分组成,语法规则确定Java程序的书写规范;类库则提供了Java程序与运行它的系统软件(Java虚拟机)之间的接口。Java类库是一组由它的发明者SUN公司以及其他软件开发商编写好的Java程序模块,每个模块通常对应一种特定的基本功能和任务,且这些模块都是经过严格测试的,因而也总是正确有效的。当自己编写的Java程序需要完成其中某一功能的时候,就可以直接利用这些现成的类库,而不需要一切从头编写,这样不仅可以提高编程效率,也可以保证软件的质量。,上一页,下一页,返回,3.3 项目支撑知识,(2)用户自己定义的类。系统定义的类虽然实现了许多常见的功能,但是用户程序仍然需要针对特定问题的特定逻辑来定义自己的类。用户按照Java的语法规则,把所研究的问题描述成Java程序中的类,以解决特定问题。一个类的定义应包含两部分:类的声明和类的实体。一、类的声明类声明包括关键字class、类名及类的属性。类名必须是合法的标识符,类的属性为一些可选的关键字。其声明格式如下,)内参数为可选项。,上一页,下一页,返回,3.3 项目支撑知识,其中,修饰符public,abstract,final说明了类的属性,className为类名,superclassName为类的父类的名字,interfaceNameList为类所实现的接口列表。修饰符含义如下:abstract:声明该类不能被实例化。final:声明该类不能被继承,即没有子类。class class name:关键字class告诉编译器表示类的声明以及类名是class Name。,上一页,下一页,返回,3.3 项目支撑知识,extends super class name:extends语句扩展super class Name为该类的父类。implements interface Name List:声明类可实现一个或多个接口,可以使用关键字implements并在其后面给出由类实现的多个接口名字列表,各接口间以逗号分隔。二、成员变量成员变量的声明方式如下:,上一页,下一页,返回,3.3 项目支撑知识,其中,/成员变量static:静态变量(类变量);相对于实例变量。final:常量。transient:暂时性变量,用于对象存档。volatile:贡献变量,用于并发线程的共享。三、成员方法方法的实现包括两部分内容:方法声明和方法体。,上一页,下一页,返回,3.3 项目支撑知识,方法声明中的限定词的含义。static:类方法,可通过类名直接调用。abstract:抽象方法,没有方法体。final:方法不能被重写。native:集成其他语言的代码。Synchronized:控制多个并发线程的访问。,上一页,下一页,返回,3.3 项目支撑知识,【例3-1】一个完整的类定义如下。,上一页,下一页,返回,3.3 项目支撑知识,项目开发背景知识 3成员变量和成员方法一、成员变量成员变量是类定义中的重要组成部分,从不同的角度区分,它可以分为多种类型。1.从变量定义的位置分根据变量定义的位置划分,变量可以分为全局变量和局部变量。,上一页,下一页,返回,3.3 项目支撑知识,全局变量:定义在类中任何方法的外部,其作用范围为该变量所属的整个类。局部变量:定义在类中某一方法的内部,其作用范围为该变量定义的地方起,至所属方法结束的地方为止。【例3-2】测试全局变量的操作。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,程序运行结果如图3-3所示。从此例我们可以看出,全局变量作用于其所在的整个类,在确保全局变量定义在类中任何方法的外部的前提下,它可以被随处安放,即使它的定义处在该全局变量的使用处之后。如例子中的全局变量var a,var b的定义语句,完全可以把其安排在类的prim()方法定义体的右括号之后,程序运行的效果相同,这一点是与C/C+所不同的。【例3-3】测试局部变量的操作。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,运行结果如图3-4所示。2.从变量的数据类型分根据变量所属的数据类型划分,变量可以分为基本类型变量和对象类型变量。所谓基本类型变量,就是指我们在第二章中讲述的8种基本数据类型,如int,double等,而由系统类库或者自定义类定义的变量,则为对象类型变量。这正如我们讲数据类型时对应的,基本类型对应的是基本变量,在一个类中又被称为成员变量。对象类型对应的就是对象类型变量,在类中又可以被称为实例变量。【例3-4】基本类型变量和对象型变量测试。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,程序运行结果如图3-5所示。,上一页,下一页,返回,3.3 项目支撑知识,【例3-5】简单数据类型与引用数据的区别。,上一页,下一页,返回,3.3 项目支撑知识,程序运行结果如图3-6所示。,上一页,下一页,返回,3.3 项目支撑知识,3.从变量的性质分根据变量的性质划分,可以将变量分为类变量和成员变量。所谓类变量(class variable),就是用关键字static声明的全局变量,它是属于类本身的,不代表任何对象的状态。所谓成员变量,就是与类变量相对的,没有用static声明的其他变量,它是与具体对象相关的,保持对象的状态。类变量的使用能满足这样的需求,即有时想有一个可以在类的所有实例中共享的变量。比如,这可以用作实例之间交流的基础或追踪已经创建的实例的数量。数值型类变量在进行数值计算时候有其特殊性,即每次参加运算时的初始值为其上次运算的结果值。,上一页,下一页,返回,3.3 项目支撑知识,类变量与成员变量的通用调用格式如下。类变量:类名.类变量名成员变量:对象名.成员变量名【例3-6】类变量和成员变量测试,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,程序运行结果如图3-7所示。此例中,设置l对象计数器counter为static型,要注意,若没有为该类变量初始化的话,那系统将为其设置默认值0。二、成员方法的使用成员方法通常用来描述该类对象所具有的功能或操作,反映对象的行为,是具有某种相对独立功能的程序模块。1.成员方法声明在Java程序中,成员方法的声明只能在类中进行,格式如下:,上一页,下一页,返回,3.3 项目支撑知识,一修饰 返回值的类型 成员方法名(形式参数表)throw 一异常表说明部分执行语句部分,上一页,下一页,返回,3.3 项目支撑知识,成员方法的声明包括成员方法头和方法体两部分,其中:成员方法头确定成员方法的名字、形式参数的名字和类型、返回值的类型、访问限制和异常处理等;方法体由包括在花括号内的说明部分和描述该方法功能实现的执行部分组成,执行部分一般由变量声明语句、赋值语句、流程控制语句、方法调用语句、返回语句等Java允许的各种语句成分组成,是程序设计中最复杂的部分,几乎会用到我们已经学习过的和将要学习的绝大多数内容。,上一页,下一页,返回,3.3 项目支撑知识,在成员方法头中:(1)修饰符。修饰符可是 public,private,protected等访问权限修饰符,也可以是static,final,native,abstract等非访问权限修饰符。访问权限修饰符指出满足什么条件时该成员方法可以被访问。非访问权限修饰符指明数据成员的使用方法。具体参阅下面有关内容。(2)返回值的类型。返回值的类型用Java允许的各种数据类型关键字(例如,int,float等)指明成员方法返回结果值的数据类型。若成员方法没有返回值,则在返回值的类型处应写上void关键字。,上一页,下一页,返回,3.3 项目支撑知识,(3)成员方法名。成员方法名也就是用户遵循标识符定义规则命名的标识符。(4)形式参数表。成员方法可分为带参成员方法和无参成员方法两种。对于无参成员方法来说则无形式参数表这一项,但其后的圆括号不可省略;对于带参成员方法来说,形式参数表指明调用该方法所需要的参数个数、参数的名字及其参数的数据类型,其格式为:(形式参数类型1,形式参数名1,形式参数类型2,形式参数名2,)(5)throws!异常表。它指出当该方法遇到一些方法的设计者未曾想到的异常问题时如何处理。这部分内容将在项目4中作专门介绍。,上一页,下一页,返回,3.3 项目支撑知识,2.成员方法引用成员方法的引用可有下述几种方式。方法语句:成员方法作为一个独立的语句被引用。例如,add(a,b)。方法表达式:成员方法作为表达式中的一部分被引用。例如,f3=2+add1(f1,f2)。方法作为参数:一个成员方法作为另一个成员方法的参数被引用。例如,add(a,add1(f1,f2),这里add1()是方法。通过对象来引用:即通过形如“对象名.方法名”的形式来引用对象,如Dane.ShowDog(25,25),这里Dane是对象名,ShowDog是方法名。,上一页,下一页,返回,3.3 项目支撑知识,3.形式参数与实际参数一般来说,可通过如下的格式来引用成员方法:成员方法名(实参列表)但在引用时应注意下述问题。对于无参成员方法来说,是没有实参列表的,但方法后的括弧不能省略。对于带参数的成员方法来说,实参的个数、顺序以及它们的数据类型必须与形式参数的个数、顺序以及它们的数据类型保持一致,各个实参间用逗号分隔。实参名与形参名可以相同也可以不同。,上一页,下一页,返回,3.3 项目支撑知识,实参也可以是表达式,此时一定要注意使表达式的数据类型与形参的数据类型相同,或者使表达式的类型按Java类型转换规则达到形参指明的数据类型。4.构造方法在类的构造中有一种特殊的成员方法,被称为构造方法。构造方法的应用通常具有明确的目的:给对象进行初始化,即对类中的成员变量赋值,这种初始化动作在new返回新创建对象的引用前完成。构造方法具有如下的明显特点。构造方法的名字与其所属类的类名相同。构造方法是给对象赋初值,没有返回值。,上一页,下一页,返回,3.3 项目支撑知识,构造方法不能被程序显式调用,由new构造对象时系统自动调用。构造方法可以有零个或多个形式参数。构造方法可在类中由用户定义,若用户没有定义,系统将自动生成一个空构造方法。构造方法可以通过重载实现不同的初始化方法。【例3-7】构造方法测试。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,程序运行结果如图3-8所示。,上一页,下一页,返回,3.3 项目支撑知识,本例中涉及到了方法的重载,可暂时简单理解为系统依据不同的参数列表调用同名的方法,如代码中catA和catB对象的构造分别调用了不同的Cat类的构造方法。)项目开发背景知识4对象的使用当我们创建了一个类,就等同于创建了一种新的数据类型,可以像使用基本数据类型一样地使用类。类定义好之后,我们将用该类定义一个实例,即该类的对象。一、对象的创建创建一个类的对象通常包括三个步骤,即声明对象、建立对象和初始化对象。,上一页,下一页,返回,3.3 项目支撑知识,1.声明对象所谓声明对象,就是确定对象的名称,并指明该对象所属的类。声明对象的格式如下:类名对象名表;其中:类名是指对象所属类的名字,它是在声明类时定义的;对象名表是指一个或多个对象名,若为多个对象名时,用逗号进行分隔。声明对象的作用是创建对象空间的管理者。例如:Dog dogA,dogB;,上一页,下一页,返回,3.3 项目支撑知识,这个语句声明了Dog类的两个对象dogA,dogB,它们可以被用来引用实际的Dog类对象空间,但必须明自此时,dogA和,dogB只是两个将来可以引用真正Dog类实例的对象名,还并不具备具体内存空间。2.建立对象所谓建立对象,实际上就是用Java提供的new关键字为对象分配存储空间。在声明对象时,只确定了对象的名称和它所属的类,并没有为对象分配存储空间,此时对象还不是类的实例。只有通过建立对象这一步,才为对象分配内存,使该对象成为类的实例。建立对象的格式如下:,上一页,下一页,返回,3.3 项目支撑知识,对象名=new构造方法();例如:dogA=new Dog();也可以在声明对象的同时建立对象,这称为创建一个对象。创建对象的格式如下:类名对象名=new构造方法();例如:Dog dogA=new Dog();其中:new是Java的关键字,也可将其称为运算符,因为new的作用是建立对象,为对象分配存储空间。执行new Dog将产生一个Dog类的对象(具备内存空间)。,上一页,下一页,返回,3.3 项目支撑知识,3.初始化对象初始化对象是指由一个类生成一个对象时,为这个对象确定初始状态,即给它的数据成员赋初值的过程,当然,它主要由一些赋值语句组成。例如:由于初始化操作是最常用的操作之一,为简化这一过程,Java还提供了专用的方法来完成它,即前面刚刚介绍的构造方法。对象创建的三个步骤在内存中都起厂相应的变化,如表3-1所示。,上一页,下一页,返回,3.3 项目支撑知识,从上表3-1中可以看出,声明对象时仅仅定义一个该类的引用变量,这时候该引用变量的值为null,意为该引用此时与任何实体空间无关。在建立对象阶段,通过new关键字申请了一个Dog类的对象空间,并同时返回厂该空间的首地址,假设该空间首地址为F000,那在执行dogA=new Dog();语句时,实际上是把地址值“F000”赋值给了引用变量dogA,注意此时,虽然一个Dog对象已经创建,但该对象内部的两个成员变量weight和height是没有被赋值的。在初始化阶段,我们才真正对这两个成员变量赋具体值。,上一页,下一页,返回,3.3 项目支撑知识,二、传值引用与传址引用Java程序中,当变量间发生赋值动作时,涉及到传值引用与传址引用的问题。所谓传值,即指“=”号两端变量各自具有独立的值空间,右端变量把自身的变量值复制给左端变量,这种方式发生在基本数据类型变量间的赋值操作。所谓传址,右端变量把自身引用(管理)的内存空间的首地址复制给左端变量,这样“=”号两端变量共同引用(管理)一个内存空间,这种方式发生在对象变量间的赋值操作。传值引用与传址引用操作相应的内存变化状况如下表3-2所示。,上一页,下一页,返回,3.3 项目支撑知识,从上表3-2可以看出,执行int b=a;语句时,基本数据类型变量b具备自身独立的内存空间,该空间内的值是对变量a的值的简单复制;执行Dog dogB=dogA时,对象型变量dogB仅仅是复制r对象型变量dogA所引用(管理)的具体对象内存空间的首地址(也即dogA变量本身的值),而不是复制dogA所引用(管理)的具体对象,这样导致对象型变量dogB和dogA具有共同的地址值,也即管理着一个共同的对象内存空间。三、自动垃圾收集机制,上一页,下一页,返回,3.3 项目支撑知识,在Java中,对于类对象的创建都需要使用new关键词,它向系统运行时申请指定类的一个对象的内存空间,并把该内存空间的首地址返回。那么当程序中不再需要这些通过new创建的对象时,怎么办呢?大家回想一下,在C/C+里面,有相应的malloc()/free()和new()/delete()两对函数来操作空间申请和释放。而Java中,而无相应的关键词来申请对象空间,而无相应的关键词来删除对象空间。难道Java中只许用户申请空间而不能删除这些空间吗?答案是否定的,其实Java内部提供了一种称为自动垃圾收集的机制来执行此项任务,这也是Java的安全性措施之一。,上一页,下一页,返回,3.3 项目支撑知识,Java的自动垃圾收集机制通过多种算法(如引用计数法(Reference Counting Collector),Tracing算法(Tracing Collector)等)来确定哪些对象空间需要被删除,无须用户主动性地去删除那些通过new申请来的对象空间。虽然Java中不需要也不建议大家去主动释放动态对象空间,但还是提供了主动释放空间的途径,即使用System类的gc()方法。使用System.gc()可以不管JVM使用的是哪一种垃圾回收的算法,都可以请求Java的垃圾回收。在命令行中有一个参数-vergosegc可以查看Java使用的堆内存的情况,它的格式如下。【例3-8】gc()方法测试。,上一页,下一页,返回,3.3 项目支撑知识,程序运行效果如图3-9所示。,上一页,下一页,返回,3.3 项目支撑知识,在这个例子中,一个新的对象被创建,由于它没有使用,所以该对象迅速地变为可达,程序运行后结果为:箭头前后的数据123 K和88K分别表示垃圾收集GC前后所有存活对象使用的内存容量,说明有123K-88K=35K的对象容量被回收,括号内的数据1984 K为堆内存的总容量,收集所需要的时间是0.0148759秒(这个时间在每次执行的时候会有所不同)。,上一页,下一页,返回,3.3 项目支撑知识,项目开发背景知识 5类的继承和多态一、继承继承是面向对象编程中的重要特性之一。继承允许创建一个通用类,它具有同类事务的一般特征。该类可以被更具体的类所继承,每个具体类都可以添加自己有特色的属性。Java中被继承的类,称为父类(或超类,superClass),继承父类的类,称为子类(或派生类,subclass)。可以把子类看成是父类的一个特殊功能版本,子类继承了父类的所有特征(成员变量和方法)。,上一页,下一页,返回,3.3 项目支撑知识,1.创建子类Java中继承是通过extends关键字来实现的。在定义类时使用extends关键字指明新定义类的父类,新定义的类称为指定父类的子类,这样就在两个类之间建立了继承关系。ex tends关键词应用的格式如下:【例3-9】继承测试,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,程序运行效果如图3-10所示。2.属性的继承父类的属性(包括所有成员变量和方法)都将被子类所继承,但被继承并不等于就一定能被访问。在Java中,只有非私有型(public型、或缺省型)的属性(变量和方法)能被同包子类所继承并直接访问,如例4-9而对于父类中私有型(private型)的属性,子类将无权直接访问。【例3-10】私有属性继承测试1。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,【运行结果】如图3-11所示此例不能正常通过编译,原因是在子类SubClass的fn3()里越权访问l 父类中的私有变量d。注意,对于任何类的private型变量,对外界而言它是隐藏的,它的访问范围仅限于其所属类的方法内部,如此例中SuperClass类的私有变量d,它可在该类的方法fn4()中被访问。那么,父类中的私有属性究竟如何被子类访问呢?可以通过子类继承一个父类的公有方法去访问该父类的私有成员变量。【例3-11】私有属性继承测试2。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,【运行结果】如图3-12所示。,上一页,下一页,返回,3.3 项目支撑知识,3.子类的构造方法Java中的构造方法一般在new关键字定义新对象的时候由系统自动调用,而当定义子类对象的时候,系统除了执行子类本身的构造方法,在默认情况下还会自动地执行父类的构造方法。【例3-12】子类构造方法测试(1)。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,【运行结果】如图3-13所示。,上一页,下一页,返回,3.3 项目支撑知识,本例不能正确通过Java编译,出现如上所示错误,原因在于执行Square的构造语句时出错。由于该Square类是Rec tangle类的子类,Java规定子类构造方法在真正被执行之前,首先需回溯执行父类的构造方法,系统在执行:Squaresquare=new Square(10);时首先执行父类Rectangle类的构造方法,默认情况下是执行父类的空构造方法,而此例Rectangle类中已经定义r显式的Rec tangle(inta,int h型的构造方法,所以系统将不再为Rectangle类生成默认的空构造方法,这样程序运行时就找不到匹配的父类构造方法了,解决的方法有多种。方法一:为父类添加空构造方法,需修改的代码如下。,上一页,下一页,返回,3.3 项目支撑知识,方法二:在子类的构造方法中明确指明需执行的父类构造方法的类型,修改的代码如下。,上一页,下一页,返回,3.3 项目支撑知识,不管使用何种方法,程序都能正确运行,得到一致的结果,如图3-14所示。,上一页,下一页,返回,3.3 项目支撑知识,二、类的多态多态的存在是类之间继承关系的必然结果,正是因为继承关系,使得两个类之间有了一种比较亲密的关系:父与子的关系。多态的概念,通俗讲,就是系统自动识别当前对象变量的类型(子类或父类),并访问其相应的属性或方法。在Java语言中,多态性体现在两个方面:由方法重载实现的静态多态性(编译时多态)和方法覆盖实现的动态多态性(运行时多态)。编译时多态在编译阶段,具体调用哪个被重载的方法,编译器会根据参数的不同来静态确定调用相应的方法。,上一页,下一页,返回,3.3 项目支撑知识,重载,是指同一个类中允许存在多个同名方法,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)的现象,重载现在可以发生在任何类中。【例3-13】编译时多态测试。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,【运行结果】如图3-15所示。2.运行时多态由于子类继承了父类所有的属性,所以子类对象可以作为父类对象使用。程序中凡是使用父类对象的地方,都可以用子类对象来代替。一个对象可以通过引用子类的实例来调用子类的方法。覆盖,是指子类中重新定义父类的同名方法的现象,如果一个类中存在着覆盖现象,则该类应为另一类的子类。覆盖方法的调用原则:Java运行时系统根据调用该方法的实例,来决定调用哪个方法。对子类的一个实例,如果子类覆盖了父类的方法,则运行时系统调用子类的方法;如果子类继承了父类的方法(未覆盖),则运行时系统调用父类的方法。,上一页,下一页,返回,3.3 项目支撑知识,【例3-14】运行时多态测试。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,【运行结果】如图3-16所示。项目开发背景知识 6访问控制与修饰符一、Java访问控制符Java语言规定类中的成员变量或方法具有4种不同的访问控制符,对应于4种不同的访问权限。表3-3列出了这些访问控制符的作用范围。(1)private,上一页,下一页,返回,3.3 项目支撑知识,类中被private关键词修饰的成员变量或方法,只能在这个类本身的方法内部被访问。如果一个类的构造方法声明为private,则该类通常为另一个类的内部类。(2)default类中不被任何访问控制符修饰的成员变量或方法属于缺省的(default)访问状态,可以被这个类本身和同一个包中的类所访问。(3)protected类中被protected关键词修饰的成员变量或方法,可以被这个类本身、它的子类(包括同一个包中以及不同包中的子类)和同一个包中的所有其他的类访问。,上一页,下一页,返回,3.3 项目支撑知识,(4)public类中被public关键词修饰的成员,可以被所有的类访问。表3-3列出了这些访问控制符的作用范转。二、Java修饰符static修饰符(1)static型变量。static型变量,即静态型变量,全局型的静态变量通常用来描述属于类的变量,我们在前面已具体介绍过,可参见3.3.3节。(2)static型方法。,上一页,下一页,返回,3.3 项目支撑知识,用static修饰符修饰的方法被称为静态方法,它是属于整个类的类方法。不用static修饰符限定的方法,是属于某个具体类对象的方法。static方法使用特点如下。static方法是属于整个类的,它在内存中的代码段将随着类的定义而分配和装载。而非static的方法是属于某个对象的方法,当这个对象创建时,在对象的内存中拥有这个方法的专用代码段。,上一页,下一页,返回,3.3 项目支撑知识,引用静态方法时,可以使用对象名做引用者,也可以使用类名做引用者;static方法只能访问static数据成员,不能访问非static数据成员,但非static方法可以访问static数据成员。static方法只能访问static方法,不能访问非static方法,但非static方法可以访问static方法。static方法不能被覆盖,也就是说,子类中不能有与父类中的static方法具有相同名、相同参数的方法。,上一页,下一页,返回,3.3 项目支撑知识,main方法是静态方法。在Java的每个Application程序中,都必须有且只能有一个mian方法,它是Application程序运行的入口点。【例3-15】StaticMethodTest.Java类方法测试。,上一页,下一页,返回,3.3 项目支撑知识,【运行结果】如图3-17所示。,上一页,下一页,返回,3.3 项目支撑知识,类似于类变量的调用,静态方法(类方法)也可以使用对象名来调用,但我们建议使用类名来调用静态方法,这样更能体现静态方法属于类的特性。如此例中,可以编写如下代码:程序运行的效果不变。此外,static型方法声明及使用的时候,有诸多地方容易出错,需引起注意如下所示。【例3-16】,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,本例程序不能通过编译,错误原因如注释所示。.static型语句块。Java语法规定类中不属于任何方法的代码可以放在一个由static修饰的语句块中,这是完全有效的,这样的语句块代码被称之为静态块代码。静态块代码中若要处理类的成员变量或方法那都只能是静态型的。当类被装载时,静态块代码只被执行一次。若类中含有不同的静态块代码,那么它们的执行顺序按照它们在类中出现的顺序被执行。【例3-17】StaticBlockTest.Java静态块语句测试。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,【运行结果】如图3-18所示。2.final修饰符.final型变量如果变量被标记为final,其结果是使它成为常量。想改变final变量的值会导致一个编译错误。下面是一个正确定义final变量的例子:,上一页,下一页,返回,3.3 项目支撑知识,如果将引用类型(即任何类的类型)的变量标记为final,那么该变量不能指向任何其他对象。但可以改变对象的内容,因为只有引用本身是final。【例3-18】FinalVarTest.Java最终变量测试。,上一页,下一页,返回,3.3 项目支撑知识,上一页,下一页,返回,3.3 项目支撑知识,【运行结果】如图3-19所示。,上一页,下一页,返回,3.3 项目支撑知识,.final型方法。在面向对象的程序设计中,子类可以利用重载机制修改从父类那里继承来的某些数据成员及成员方法,这给程序设计带来方便的同时,也给系统的安全性带来了威胁。为此,Java语言提供了final修饰符来保证系统的安全。用final修饰符修饰的方法称为最终方法,如果类的某个方法被final