Download presentation
Presentation is loading. Please wait.
Published byΑἴσωπος Αλεξανδρίδης Modified 6年之前
1
第5章 面向对象程序设计 本章要点 5.1 面向对象程序设计概述 5.2 Java语言的面向对象程序设计 5.3 方法的使用和对象数组
第5章 面向对象程序设计 本章主要介绍Java语言面向对象的基本概念、面向对象程序设计方法、接口和包的概念,以及域和方法的定义与实现。 本章要点 5.1 面向对象程序设计概述 5.2 Java语言的面向对象程序设计 5.3 方法的使用和对象数组 5.4 类的继承和多态 5.5 包和访问控制符 5.6 接口 思考与练习5
2
5.1 面向对象程序设计概述 什么是面向对象 术语“面向对象”是由英文Object Oriented翻译而来的,简称为OO。面向对象的程序设计是目前软件工业的主流,绝大多数的系统程序、应用程序都是采用面向对象的思想来设计开发的。 在面向对象概念中,整个世界是由各种各样的对象(Object)组成的。世界上存在着许多类型相同的对象,也存在着许多类型不相同的对象。例如:一辆自行车和一根铅笔是类型不同的两个对象,而李明的自行车和李芳的自行车可以看作是类型相同的两个对象。 早期的计算机程序设计语言经历了面向机器(Machine-Oriented)、面向过程(Procedure-Oriented)等阶段。随着计算机技术的发展,以及要解决的问题越来越复杂,早期的程序设计语言已经不能适应实际的需求。从上个世纪60年代末,陆续开发出了多个面向对象的程序设计语言,例如:C++、Java等。面向对象程序设计语言的出现带动了面向对象的程序设计方法。
3
5.1 面向对象程序设计概述 什么是面向对象 面向对象的程序设计是以要解决的问题中所涉及的各种对象为主体,力求程序设计符合人们日常的思维习惯,降低问题的难度和复杂性,提高编程的效率。使用面向对象的程序设计方法来解决问题就是从实际问题中抽象并封装数据和操作的对象,通过定义其状态和操作其行为来表述对象的特征和功能。此外,还可以通过定义接口来描述对象的地位以及与其他对象的关系,最终形成一个广泛联系的可理解、可扩充、可维护及更接近于问题本来面目的动态对象模型系统。
4
5.1 面向对象程序设计概述 5.1.2 常用术语的含义 在面向对象程序设计中,经常使用一些术语,下面介绍几个常用的术语。
5.1 面向对象程序设计概述 常用术语的含义 在面向对象程序设计中,经常使用一些术语,下面介绍几个常用的术语。 (1)对象(Object):对象是面向对象程序设计的核心,也是程序的主要组成部分。一个程序实际上就是一组对象的总和。 在现实世界中,人们面对的所有事物都可以称为对象,例如,电视、台灯、猫、狗、草木等等。在Java语言中,对象是由数据以及对数据进行处理的方法组成的,是对现实世界的抽象描述。 在面向对象程序设计中,通过对象的状态(States)和行为(Behaviors)两个方面描述对象。每一个对象都是由状态和行为两个最基本的部分组成的。虽然同一类对象的行为都是一样的,但是每个对象的状态都是独立与其他对象的。例如:改变速度是任何一辆自行车都具有的行为,但是每辆自行车的品牌、型号、颜色、所有者等状态又是不同。
5
5.1 面向对象程序设计概述 常用术语的含义 (2)类(Class):对象是由类创建的,类是同一类型对象的集合和抽象。例如,汽车有很多种类,包括轿车、卡车、公共汽车等。它们是不同的对象,但是都属于车类,存在着许多共同点,例如,都可以加速、刹车等。 在Java语言中,每一个类是一种对象类型数据,属于不同类的对象具有不同的数据类型。一个对象被称为其类的一个实例,是该类的一次实例化的结果。例如:月饼模子可以看作是月饼的类,使用模子做月饼的过程实际上就是一个实例化的过程,最终制作出的月饼是该月饼模子的一个对象。 类还可以具有子类,子类除了具有类的所有状态和行为外,还具有自己特有的状态和行为。例如:哺乳动物类是动物类的一个子类,它除了具有动物类共有的状态和行为外,还具有胎生、哺乳等哺乳动物类特有的状态和行为。
6
5.1 面向对象程序设计概述 常用术语的含义 (3)域(Field):域是类或者对象的状态属性的总称。它可以是普通数据类型的变量,也可以是其他类的对象。例如,在自行车类中,品牌和颜色可以是String类型数据;型号可以是int类型数据;当前速度可以是double类型数据。 在Java语言中使用实例变量来表达类或者对象的状态,并且这些变量必须在类方法的外边定义,作用于整个类。 (4)方法(Method):方法是类的行为属性的总称。一个类可以有多个方法,表示该类所具有的功能和操作。通过对象调用类中的方法就可以改变对象域中变量的值。例如:自行车类具有加速和减速的方法,通过一个自行车对象调用加速方法就可以改变对象中保存当前速度的实例变量的值。
7
5.1 面向对象程序设计概述 程序设计过程 使用面向对象方法解决问题的过程可以大体划分为面向对象分析(Object Oriented Analysis,简称OOA)、面向对象设计(Object Oriented Design,简称OOD)和面向对象编程(Object Oriented Programming,OOP)三大步骤。 (1)面向对象分析(OOA)。面向对象分析的主要作用是明确使用程序的用户、用户可以进行的操作,以及数据的输入、输出和储存,并且用标准化的面向对象模型规范地表述这些内容,最后形成面向对象分析模型,即OOA模型。 在分析问题时,要抽取所有需要的对象实体,然后确定这些对象的状态和行为,以及它们之间的相互关系。一般来说,解决一个问题会涉及到多个对象,所以这些对象之间的关系一定要明确,从而反映出整个程序的功能和状态。例如:自动取款机程序的使用用户包括银行和用户,它有可能涉及到的对象包括用户、帐户、自动取款机和提款卡等等。
8
5.1 面向对象程序设计概述 程序设计过程 (2)面向对象设计(OOD)。面向对象设计是将在面向对象分析步骤中创建的OOA模型加以扩展并得到面向对象设计步骤中的OOD模型。 面向对象设计在OOA模型的基础上引入界面管理、任务管理和数据管理三部分的内容,进一步扩充OOA模型。界面管理负责整个系统的人机对话界面的设计,任务管理负责处理整个程序资源管理功能的工作以及设置客户与服务器之间的接口,数据管理负责设计程序与数据库的交换方式。 面向对象设计还需要明确每个类方法的参数、返回值、功能等,以及各类之间的相容性和一致性的验证,对各个类、类内成员的访问权限的严格合理性的验证,也包括验证对象类的功能是否符合用户的需求。例如:自动取款机的OOD模型要包括用户、帐户、自动取款机的人机对话界面设计,使用自动取款机的用户和自动取款机服务器之间的操作,自动取款机服务器与数据库之间的操作等等。
9
5.1 面向对象程序设计概述 程序设计过程 (3)面向对象编程(OOP)。面向对象编程就是具体的程序编写阶段,其主要过程是先选择一种合适的面向对象编程语言,再用选定的语言编写程序实现设计步骤中对各个对象的详尽描述,然后将编写好的各个类根据其关系集成为整个程序,最后通过各种实例测试找出程序的漏洞并改善程序,最终完成整个软件的开发。
10
5.1 面向对象程序设计概述 5.1.4 面向对象程序设计的特点
5.1 面向对象程序设计概述 面向对象程序设计的特点 面向对象程序设计提高了软件的生产效率和程序模块的重复使用率,并且降低了维护成本。面向对象程序设计的主要特点是: (1)封装(Encapsulation):封装就是将对象的数据和基于数据的方法封装在一起成为一个整体——类。所有的程序编写基本上都是通过创建类的对象,然后以对象为载体,进行数据交流和方法的执行。 封装是一种数据信息隐藏技术,使用者只需要知道对象中变量和方法的功能,而不必知道行为实现的细节,也就是说,类的使用者与设计者是分开的。此外,封装使得类的可重用性大为提高。 (2)多态(Ploymorphism):多态是指程序的多种表现形式。在同一个类中,同名但参数不同的多个方法(方法重载)是多态的一种表现形式。另一种表现形式是子类对父类方法的覆盖或者子类对抽象父类中的抽象方法的具体定义。
11
5.1 面向对象程序设计概述 5.1.4 面向对象程序设计的特点
5.1 面向对象程序设计概述 面向对象程序设计的特点 (3)继承(Inheritance):继承是指一个类拥有另一个类的所有变量和方法。被继承的类称为父类,继承了父类的所有数据和操作的类称为子类。继承使得程序结构清晰,降低编程和维护的工作量。 (4)抽象(Abstraction):抽象是具体事物一般化的过程,即对具有特定属性的对象进行概括,从中归纳出这一类对象的共性,并从共同性的角度描述共有的状态和行为特征。 抽象包括数据抽象和方法抽象两个方面。数据抽象用来描述某类对象的共同状态;方法抽象用来描述某类对象的共同行为。
12
5.2 Java语言的面向对象程序设计 域 我们在前面介绍过域是类或者对象的状态属性的总称。它可以是普通数据类型的变量,也可以是其他类的对象类型变量。域常见的有实例变量、静态变量和最终变量3种形式。分别介绍如下。 1.实例变量 实例变量(Instance Variable)用来储存某个类对象的状态值。它必须在类内、任何方法外被定义,一般位于整个类语句体的最前端。其修饰符可以是public或者private,但是不能使用static。实例变量的使用范围是整个类,也就是说可以在类中的任意方法内被使用。实例变量是依据其对象存在的,当运行程序创建对象的同时,创建了其实例变量,当程序运行完成,对象消失,其实例变量也同时消失。
13
5.2 Java语言的面向对象程序设计 域 变量name、age、gender、height和weight分别表示人的姓名、年龄、性别、身高和体重。当创建People类的对象时,每个对象的实例变量也是这5个变量,只是对象之间的变量值有可能不同。如图5.3所示为创建了3个People类对象的演示效果图。 图5.3 3个People类对象
14
5.2 Java语言的面向对象程序设计 5.2.1 域 2.静态变量
域 2.静态变量 用修饰符static修饰的变量称为类静态变量,也叫做静态变量或者类变量。静态变量是类的变量,不属于任何一个类的具体对象实例。它不保存在某个对象实例的内存空间中,而是保存在类的内存空间的公共存储单元中。也就是说,不论一个类具有多少个对象,静态变量只有一个,任何一个类的对象访问它,取得的都是相同的数值。同样地,任何一个类的对象去修改它,也都是在对同一个内存单元进行操作。静态变量可以通过类名直接访问,也可以通过对象来调用。采用这两种方法取得的结果是相同的。
15
5.2 Java语言的面向对象程序设计 5.2.1 域 2.静态变量
域 2.静态变量 静态变量与实例变量虽然都是在类内、类中方法之外定义的变量,但是它们有着本质的不同。 (1)实例变量:一般使用private或者public作为修饰符。每个类的对象都具有一套属于自己的、在类中定义的实例变量。每个对象只能修改或者访问其自身的实例变量,不会影响其他对象的实例变量。 (2)静态变量:使用static修饰符。每个类的所有对象共同拥有一套类的静态变量。类和其对象都可以修改或者访问静态变量。
16
5.2 Java语言的面向对象程序设计 5.2.1 域 3.最终变量
域 3.最终变量 在编写程序时,可以给某些经常要使用具有特殊含义或者内容复杂的常量,取一个类似于变量名的标识符,这样就可以通过使用这个变量名称来引用其对应的常量,而不是每次直接键入常量数值。这种做法的最主要目的是使程序更加清楚,利于其他人阅读、理解。 使用修饰符final修饰的变量是最终变量,其保存的数据在程序的整个执行过程中都不会改变。通常,我们在final前面再加上修饰符static,那么这个变量的实际含义就是常量。 如果在定义最终变量时,没有给其赋值,则按该类型数据的默认值进行初始化。final修饰符可以修饰局部变量,也必须且只能赋值一次,它的取值在变量存在期间不会改变。 此外,使用修饰符volatile修饰变量被称为易失域,通常用于进行多线程编程。这种变量可以同时被多个线程控制和修改变量值。
17
5.2 Java语言的面向对象程序设计 构造方法 构造方法(Constructor Method),也称为构造函数,是一种特殊的方法。在创建对象的同时,调用这个对象所属类的构造方法来完成对象实例变量的初始化。 构造方法的形式如下: public 类名( 参数 ) { 语句体 } 其中的语句体为初始化实例变量的赋值语句,可以使用参数值作为变量的初值,也可以直接给变量赋具体的数值。 一般来说,构造方法具有以下几个的特点:
18
5.2 Java语言的面向对象程序设计 5.2.2 构造方法 (1)构造方法的方法名与其所在类的名称相同。
构造方法 (1)构造方法的方法名与其所在类的名称相同。 (2)虽然构造方法没有返回值,但是也不能有void关键字。 (3)构造方法的修饰符总是public。 (4)构造方法的主要作用是完成对类对象实例变量的初始化工作。 例如,可以为People类增加一个如下所示的构造方法 public People() { name = "沈昕"; age = 26; gender = 'F'; height = 1.62; weight = 55.5; } 在上面的构造方法中,一共给5个实例变量赋了初值。当调用该构造方法时,就可以完成对5个实例变量的初始化。
19
5.2 Java语言的面向对象程序设计 构造方法 如果希望在创建对象时,其实例变量具有不同的初值,可以通过传递参数并将参数值赋给实例变量的方法来实现。构造方法的参数要与实例变量一一对应,例如:People类的另一种构造方法为: public People( String initName, int initAge, char initGender, double initHeight, double initWeight ) { name = initName; age = initAge; gender = initGender; height = initHeight; weight = initWeight; } 一般情况下,一个类中可以有一个或者多个构造方法,它们的方法名称相同但是参数不同,相当于方法的重载。我们将在后面具体介绍方法重载。
20
5.2 Java语言的面向对象程序设计 方法 除了构造方法外,类中还有许多描述类行为的方法,这些方法可以分为实例方法和静态方法两种。 1.实例方法 它属于每个对象,只能通过类的对象调用。实例方法用来定义某个类的行为,也就是说类的对象所能进行的操作。与实例变量一样,实例方法的修饰符可以是public或者private,但是不能用static。如果希望实例方法可以在类之外被访问,则使用public;如果希望实例方法只在类内被访问,则使用private。例如:在People类中,我们可以定义一个setName()方法用来改变People类某个对象的姓名,该方法内容如下。 public void setName( String newName ) { name = newName; }
21
5.2 Java语言的面向对象程序设计 5.2.3 方法 2.静态方法
方法 2.静态方法 与静态变量类似,静态方法的本质是属于整个类的,而不属于某个实例对象。因为静态方法属于类本身,所以只要定义了类,它的静态方法就存在,就可以直接使用类来调用。 在使用静态方法时要注意以下几个问题: (1)使用static修饰的静态方法是属于某个类的,它在内存空间中的内容将随着类的定义而进行分配和装载,不被任何一个对象所单独拥有。 (2)静态方法不能操纵和处理属于某个对象的实例变量,而只能处理属于整个类的静态变量,也就是说静态方法只能处理静态变量或者调用静态方法。 (3)因为静态方法不能访问实例变量,所以在静态方法中不能使用关键字this。
22
5.2 Java语言的面向对象程序设计 5.2.3 方法 2.静态方法
方法 2.静态方法 (4)需要调用某个静态方法时,可以使用其所属的类的名称直接调用,也可以用类的某个具体的对象名调用,其形式为: 类名.静态方法名; 或者 对象名.静态方法名; 我们前面介绍的Math类中的abs()、max()等方法,以及Integer类中的parseInt()方法等就是静态方法,直接用类名进行访问。 作为程序入口的main()方法必须要用static来修饰,也是因为Java运行时系统在开始执行一个程序前,并没有生成类的一个对象,它只能通过类名来调用main()方法作为程序的入口。
23
5.3 方法的使用和对象数组 调用方法 在完成类程序的编写后,就可以在其他程序中创建该类的对象,并调用该类的实例方法。注意,类的程序和使用类的程序要保存在同一个目录下。 1.调用构造方法 如果在定义类对象时没有定义任何构造方法,系统会自动产生一个构造方法,无需定义,称为默认构造方法。默认构造方法不带任何形式的参数,并且方法体为空。 例如,如果上面的People类没有定义构造方法,则系统产生的默认构造方法如下: People(){ }
24
5.3 方法的使用和对象数组 调用方法 如果要使用People类的构造方法创建People类对象,则必须使用关键字new,例如,下面两种方法都可以定义People类的对象。其中关键字new后边为所调用的People类的第一种构造方法。 People p1, p2; p1 = new People(); p2 = new People(); 或者 People p1 = new People(); People p2 = new People(); 创建的对象p1和p2的示意图如图5.4所示。显而易见,对象p1和p2具有相同的姓名、年龄、性别、身高和体重。
25
5.3 方法的使用和对象数组 调用方法 图5.4 使用第一种构造方法创建对象 图5.4 使用第一种构造方法创建对象
26
5.3 方法的使用和对象数组 调用方法 如果使用People类中带有参数的第二种构造方法,则可以创建实例变量不相同的对象。例如,使用下面的语句创建对象p1和p2,其实例变量示意图如图5.5所示。 People p1 = new People( "沈昕", 26, 'F', 1.62, 55.5 ); People p2 = new People( "宁普", 17, 'M', 1.82, 75.2 ); 图5.5 使用第二种构造方法创建对象
27
5.3 方法的使用和对象数组 调用方法 图5.5 使用第二种构造方法创建对象 图5.5 使用第二种构造方法创建对象
28
5.3 方法的使用和对象数组 调用方法 当然我们也可以使用带有参数的构造方法创建一个对象,再使用不带参数的构造方法创建另一个对象。例如,使用下面的语句创建对象p1和p2,其实例变量示意图如图5.6所示。 People p1 = new People(); People p2 = new People( "肖琳", 48, 'F', 1.55, 41.8 ); 图5.6 两种构造方法混合使用创建对象
29
5.3 方法的使用和对象数组 5.3.1 调用方法 2.调用实例方法
5.3 方法的使用和对象数组 调用方法 2.调用实例方法 在调用某个类中的实例方法之前,要先创建该类的对象,然后通过该对象并且使用符号“.”来调用所要访问的实例方法。 例如,下面是某个程序中的两条语句。 People p1 = new People(); p1.setName( "李芳" ); 其中,第一条语句是调用People类的第一种构造方法来创建对象p1,第二条语句是通过对象p1调用setName()方法来改变对象p1实例变量name的值。对象p1实例变量值前后变化的示意图如图5.7所示。 图5.7 setName()的作用
30
5.3 方法的使用和对象数组 5.3.1 调用方法 3.toString()方法
5.3 方法的使用和对象数组 调用方法 3.toString()方法 在实例41的Rectangle类中,定义了一个toString()方法,其返回值为对象的信息,一般使用打印语句将该信息显示在屏幕上。在Java语言中toString()方法是一个具有特殊含义的方法,一般用一个字符串来描述对象的信息。使用System.out.println()方法来打印对象的信息时,不需要明确地调用toString()方法,只要写出对象的名称即可。 例如:假设在应用程序中,已经创建了两个Rectangle类的对象r1和r2,则显示其具体信息的打印语句可以写为: System.out.println( "第一个矩形的信息:" + r1 ); System.out.println( "第二个矩形的信息:" + r2 );
31
5.3 方法的使用和对象数组 5.3.2 访问方法 3.toString()方法
5.3 方法的使用和对象数组 访问方法 3.toString()方法 当遇到对象名r1和r2时,系统会自动调用其相应的toString()方法,打印的效果与下面的打印语句完全相同。 System.out.println( "第一个矩形的信息:" + r1.toString() ); System.out.println( "第二个矩形的信息:" + r2.toString() ); Java语言提供的大多数类都具有toString()方法,用户可以直接调用,而不需要自行编写额外的语句来显示对象的信息。
32
5.3 方法的使用和对象数组 5.3.2 访问方法 1.修饰符public和private
5.3 方法的使用和对象数组 访问方法 1.修饰符public和private 对于类中的实例变量和实例方法,一般使用修饰符public或者private。 (1)public:表示该实例变量或者实例方法可以在其所在的类的内部或者外部被访问和调用。大多数情况下,我们定义实例方法为public。 (2)private:表示该实例变量或者实例方法只可以在其所在的类的内部被访问和调用。大多数情况下,我们定义实例变量为private。 如果我们定义实例变量为public,则可以通过对象直接修改该变量。如果实例变量的修饰符为private,则必须在其所在类中添加一个实例方法来修改变量的值。 很显然将实例变量的修饰符设置为public后,可以更方便地在应用程序中改变变量的值。但是为什么大多数程序都将实例变量定义为private,然后再通过实例方法来改变其值呢?我们以实例41中的Rectangle.java程序为例来解释原因。
33
5.3 方法的使用和对象数组 5.3.2 访问方法 1.修饰符public和private
5.3 方法的使用和对象数组 访问方法 1.修饰符public和private 如果将程序内的实例变量width和length的修饰符改写为public,那么在应用程序中,我们可以通过创建Rectangle类的对象r1来访问这两个实例变量。假设应用程序中有下面这样两条语句: r1.width = -20; r1.length = -35 实例变量width和length的值改变为-20和-35,一个矩形的宽度和长度值为负数是不符合常理的。但是因为变量width和length的修饰符是public,所以无法限制其他应用程序在调用这两个变量时,赋予其数值的范围。 如果将变量width和length的修饰符设置为private,则我们可以通过在Rectangle类中添加如下的实例方法来控制变量width和length中的数值。
34
5.3 方法的使用和对象数组 访问方法 public void setWidth( int newWidth ) { if ( newWidth > 0 ) width = newWidth; else width = 0; } public void setLength( int newLength ) if ( newLength > 0 ) length = newLength; length = 0; 其中的参数newWidth和newLength是其他应用程序赋予变量width和length的值,当该值大于零时,变量width和length保存该值;当该值小于等于零时,变量width和length的值为零。这就保证了不会出现矩形宽度和长度值为负数的情况。
35
5.3 方法的使用和对象数组 访问方法 2.访问方法 访问方法(Accessor Method)是类中一种可以修改和获取private实例变量值的实例方法。为了与其他实例方法区别,一般使用set或者get再加实例变量名称作为该方法的名称。比如,setName()表示修改实例变量name的值;getHeight()表示获取实例变量height的值。该方法的修饰符必须为public。 在编写Rectangle类时,并不是必须具有以上所有的访问方法,可以根据用户的需求范围来确定添加哪些访问方法。例如,用户要求矩形的位置是固定的,只能改变其宽度和长度,那么就不需要setX()和setY()方法。此外,这些方法的内容并不是固定的,以上所给出的只是其最简单的语句体。根据要用户要求,方法中内容可以随意更改。例如,前面介绍的setWidth()方法和setLength()方法。
36
5.3 方法的使用和对象数组 方法重载 方法的重载是指在同一个类中,定义方法名称相同但参数不同的多个方法。当调用某个重载的方法时,Java会根据参数的类型、个数和顺序的不同,调用与之相符的方法。例如,在Math类中,许多方法都是有重载的,例如:求绝对值方法abs()就有double、float、int和long四种不同的参数类型。再比如,前面介绍的构造方法,也是方法名称相同但参数不同。每个重载方法中的语句体可以相同也可以不同。
37
5.3 方法的使用和对象数组 5.3.4 this 1.关键字this的作用
5.3 方法的使用和对象数组 this 1.关键字this的作用 当需要在类的实例方法中,指向调用该实例的对象时,可以使用关键字this。在大多数情况下,关键字this不是必须使用的,可以被省略。 例如:Rectangle类中的setPosition()实例方法可以被写成如下形式: public void setPosition( int newX, int newY ) { this.x = newX; this.y = newY; } 其中,this表示当前调用该方法的Rectangle类对象。
38
5.3 方法的使用和对象数组 5.3.4 this 1.关键字this的作用 如果在应用程序中的语句为:
5.3 方法的使用和对象数组 this 1.关键字this的作用 如果在应用程序中的语句为: r1.setPosition( 100, 200 ); 则在执行setPosition()方法时,关键字this代表调用该方法的对象变量r1。如果在应用程序中的语句为: r2.setPosition( 70, 10 ); 则在执行setPosition()方法时,关键字this代表调用该方法的对象变量r2。 事实上,如果在setPosition()方法中不使用关键字this,程序同样可以正常地编译和运行,所以在类似这种情况下可以忽略使用this。 在Java语言中,系统会自动在调用所有实例变量和实例方法时与this关键字联系在一起,因此,使用this在某些情况下是多余的。
39
5.3 方法的使用和对象数组 5.3.4 this 1.关键字this的作用 如果在应用程序中的语句为:
5.3 方法的使用和对象数组 this 1.关键字this的作用 如果在应用程序中的语句为: r1.setPosition( 100, 200 ); 则在执行setPosition()方法时,关键字this代表调用该方法的对象变量r1。如果在应用程序中的语句为: r2.setPosition( 70, 10 ); 则在执行setPosition()方法时,关键字this代表调用该方法的对象变量r2。 事实上,如果在setPosition()方法中不使用关键字this,程序同样可以正常地编译和运行,所以在类似这种情况下可以忽略使用this。 在Java语言中,系统会自动在调用所有实例变量和实例方法时与this关键字联系在一起,因此,使用this在某些情况下是多余的。 2.关键字this最常见的应用 关键字this最常见的应用是在类的构造方法和实例方法中解决局部变量与实例变量同名的问题。例如,下面一段程序: public class People { private String name; private int age; private char gender; private double height; private doublet weight; public People( String name, int age, char gender, double height, double weight ) name = name; age = age; gender = gender; height = height; weight = weight; } … … 在上面的一段程序中,共有name、age、gender、height和weight5个实例变量。在构造方法中的5个参数的变量名称与实例变量的名称一一对应相同。在参数名或者局部变量名与实例变量同名的时候,由于参数变量和局部变量的优先级高,所以在方法体中参数名或者局部变量名将隐藏同名的实例变量。这种情况在Java语言中是不被允许的。如果想使实例变量和方法的参数或方法本身定义的局部变量同名的话,就需要用一种方法使实例变量与和其同名的方法参数或局部变量区分开来,这就要使用到this关键字。 下面的一段程序改写了上面的程序,使People类的构造方法可以合法地使用与实例变量名称相同的参数。 this.name = name; this.age = age; this.gender = gender; this.height = height; this.weight = weight; 其中,使用this调用的都是实例变量,例如:this.name,而name是参数变量。 由上面的实例,我们可以看出,this在方法体中用来指向调用当前正在执行方法的对象。当然我们也可以通过使用与实例变量名不同的参数名或者局域变量名来避免这个问题。 3.在构造方法中使用this调用另一个构造方法 关键字this还有一个用法,就是在构造方法的第一条语句使用this语句,它的形式是this(参数),这个构造方法就会调用同一个类的另一个构造方法。例如,下面的程序: private double weight; public People( String name, int age, char gender ) this( name, age, gender, 0, 0 ); public Person( String name, int age, char gender, double height, double weight ) 其中,People类有两个不同的构造方法public People( String name, int age, char gender )和public Person( String name, int age, char gender, double height, double weight ),它们参数的个数不一样。在第一个构造方法中使用this( name, age, gender, 0, 0 );语句调用带有5个参数的第二个构造方法,这实际是方法的一种重载现象。 使用这种方法创建对象的好处是,不论应用程序如何调用构造方法,5个实例变量都具有初值。如果在应用程序中使用People p1 = new Person( "沈昕", 26, 'F' );语句,就会先调用People类中的第一个构造方法,然后再自动调用第二个构造方法,并设定实例变量height和weight的初值为0。 要注意的是,由修饰符static修饰的静态变量不能使用this来调用。
40
5.3 方法的使用和对象数组 5.3.4 this 2.关键字this最常见的应用
5.3 方法的使用和对象数组 this 2.关键字this最常见的应用 关键字this最常见的应用是在类的构造方法和实例方法中解决局部变量与实例变量同名的问题。 this在方法体中用来指向调用当前正在执行方法的对象。当然也可以通过使用与实例变量名不同的参数名或者局域变量名来避免这个问题。 3.在构造方法中使用this调用另一个构造方法 关键字this还有一个用法,就是在构造方法的第一条语句使用this语句,它的形式是this(参数),这个构造方法就会调用同一个类的另一个构造方法。使用这种方法创建对象的好处是,不论应用程序如何调用构造方法,5个实例变量都具有初值。如果在应用程序中使用People p1 = new Person( "沈昕", 26, 'F' );语句,就会先调用People类中的第一个构造方法,然后再自动调用第二个构造方法,并设定实例变量height和weight的初值为0。 要注意的是,由修饰符static修饰的静态变量不能使用this来调用。
41
5.3 方法的使用和对象数组 5.3.5 对象比较和对象数组 1.对象相等
5.3 方法的使用和对象数组 对象比较和对象数组 1.对象相等 在Java语言中,对象相等有两种含义。一种是参考相等(Reference Equality),另一种是数值相等(Value Equality) (1)参考相等。参考相等是指两个对象指向相同的内存空间,具有共同的实例变量。例如,下面的语句。 Rectangle r1, r2; r1 = new Rectangle( 20, 60, 10, 50 ); r2 = r1; r2.setPosition( 40, 40 ); 其中r2 = r1;语句表示对象r2与对象r1指向同一个内存空间。当使用r2.setPosition( 40, 40 );语句改变对象r2的矩形位置时,也相当于改变了对象r1的矩形位置。对象r1和r2的关系示意图,如图5.9所示。
42
5.3 方法的使用和对象数组 5.3.5 对象比较和对象数组 1.对象相等 图5.9 对象参考相等
5.3 方法的使用和对象数组 对象比较和对象数组 1.对象相等 图5.9 对象参考相等 当需要判断两个对象是否是参考相等时,使用关系运算符==来组成if语句的表达式。例如,判断Rectangle类对象r1和r2是否参考相等的if-else语句。 if ( r1 == r2 ) System.out.println( "r1与r2参考相等" ); else System.out.println( "r1与r2参考不相等" );
43
5.3 方法的使用和对象数组 5.3.5 对象比较和对象数组 1.对象相等
5.3 方法的使用和对象数组 对象比较和对象数组 1.对象相等 (2)数值相等。数值相等是指两个同类对象的所有实例变量值都一一对应相等。例如,下面的语句。 Rectangle r1, r2; r1 = new Rectangle( 20, 60, 10, 50 ); r2 = new Rectangle( 20, 60, 10, 50 ); r2.setPosition( 40, 40 ); 其中,对象r1和r2各自指向不同的内存空间,但是它们实例变量的初始化值完全相同。当使用r2.setPosition( 40, 40 );语句改变对象r2的矩形位置时,并没有改变对象r1的矩形位置。对象r1和r2的关系示意图,如图5.10所示。
44
5.3 方法的使用和对象数组 对象比较和对象数组 图5.10 对象数值相等
45
5.3 方法的使用和对象数组 5.3.5 对象比较和对象数组 1.对象相等
5.3 方法的使用和对象数组 对象比较和对象数组 1.对象相等 当需要判断两个对象是否是数值相等时,可以通过调用对象的实例方法equals()来实现。例如 if ( r1.equals( r2 ) ) System.out.println( "r1与r2数值相等" ); else System.out.println( "r1与r2数值不相等" ); 相应地,在Rectangle类中,需要添加实例方法equals(),其内容如下。 public boolean equals( Rectangle r ) { boolean b = ( x == r.x ) && ( y == r.y ) && ( width == r.width) && ( height == r.height ); return b; } 在Java语言提供的许多标准类中已经定义了equals()实例方法,我们不要再编写上面的方法,可以直接使用。最常用的是前面介绍过的String类中判断两个字符串是否相等的equals()方法。
46
5.3 方法的使用和对象数组 5.3.5 对象比较和对象数组 2.对象参数和默认值
5.3 方法的使用和对象数组 对象比较和对象数组 2.对象参数和默认值 在将两个对象进行某种比较时,一定要注意所调用的实例变量的修饰符是private,还是public的。如果是public修饰符,则可以直接使用两个对象进行比较。例如: r1.width < r2.width r3.length == r4.length 如果修饰符是private,则必须在对象的类中添加一个进行比较的实例方法,然后通过调用该方法和传递对象参数来完成比较。这是因为Java不允许在类之外访问其private实例变量,只允许在类内访问其对象的private实例变量,如图5.11所示。 每种类型的变量都有其默认值,例如,int类型变量的默认值为0,boolean类型变量的默认值为false。对象变量的默认值为null,表示一个变量还没有指向任何特定的对象。定义一个对象变量后,其默认值为null,创建该变量后null被具体的对象取代。当对象变量的值为null时,不可以通过其调用任何实例变量和实例方法,否则会发生NullPointerException错误。 图5.11 访问权限
47
5.3 方法的使用和对象数组 对象比较和对象数组 2.对象参数和默认值 图5.11 访问权限
48
5.3 方法的使用和对象数组 5.3.5 对象比较和对象数组 3.对象数组
5.3 方法的使用和对象数组 对象比较和对象数组 3.对象数组 对象数组的定义和创建与普通类型的数组完全一样,其定义形式也有以下两种: 类名称 数组名[]; 类名称[] 数组名; 创建对象数组的形式为: 数组名 = new 类名称[数组元素的个数]; 对象数组与普通类型的数组的不同之处在于数组元素的初始化。因为对象数组的每一个元素实际上就是类的一个对象,所以需要按照创建对象的方法来初始化数组元素,也就是说需要使用关键字new来调用类的构造方法。
49
5.4 类的继承和多态 类继承的概念 类的继承(Inheritance)是面向对象程序设计中的一个重要特色。类继承也称为类派生,是指一个类可以继承其它类的所有内容,包括变量和方法。被继承的类称为父类或者超类(Superclass),继承后产生的类成为子类或者派生类(Subclass)。 在Java语言中,可以在已有的大量类的基础上编写新的类。新编写的类如果继承了已有的类,则除了具有父类中的所有变量和方法外,还要再添加自己本身特有的变量或者方法。这种编程方法大大地提高了程序内容的可复用性,缩短了软件开发的周期。如果对新建的类再进行修改扩充,可以再派生出新的类。重复下去,每一次的修改扩充都不会影响原有的类,这样就大大地提高了程序的可扩充性。
50
5.4 类的继承和多态 类继承的概念 不断派生新类的过程是一个描述现实世界的层次关系的过程。为此,首先要建立一个简单的类,以其为基础,派生出不同层次的子类。 例如:我们将在现实世界中的事物看成一个“物质对象”类,那么其中一部分具有生命的事物可以看成是“动物”类。在“动物”类中,具有胎生、身体恒温等特征的事物可以看成是“哺乳动物”类。在“哺乳动物”类中又有“人”类。在这个层次关系中,“哺乳动物”类是“人”类的父类,“动物”类是“哺乳动物”类的父类,“物质对象”类是“动物”类的父类。 在Java语言中,每一个类只可以有一个父类,不允许有多个父类。但是,一个类可以有多个子类。父类含有其所有子类共同的内容,每一个子类各自具有与其他子类不相同的内容。例如,“狗”类和“人”类都是“哺乳动物”类的子类,它们即具有胎生、哺乳、恒温等“哺乳动物”类的共同特点,又具有各自的不同的特点。例如:“狗”类有尾巴,而“人”类使用语言。图5.15所示为这三者之间的关系示意图。
51
5.4 类的继承和多态 类继承的概念 图5.15 三者之间的关系
52
5.4 类的继承和多态 类继承的概念 不断派生新类的过程是一个描述现实世界的层次关系的过程。为此,首先要建立一个简单的类,以其为基础,派生出不同层次的子类。 例如:我们将在现实世界中的事物看成一个“物质对象”类,那么其中一部分具有生命的事物可以看成是“动物”类。在“动物”类中,具有胎生、身体恒温等特征的事物可以看成是“哺乳动物”类。在“哺乳动物”类中又有“人”类。在这个层次关系中,“哺乳动物”类是“人”类的父类,“动物”类是“哺乳动物”类的父类,“物质对象”类是“动物”类的父类。 在Java语言中,每一个类只可以有一个父类,不允许有多个父类。但是,一个类可以有多个子类。父类含有其所有子类共同的内容,每一个子类各自具有与其他子类不相同的内容。例如,“狗”类和“人”类都是“哺乳动物”类的子类,它们即具有胎生、哺乳、恒温等“哺乳动物”类的共同特点,又具有各自的不同的特点。例如:“狗”类有尾巴,而“人”类使用语言。图5.15所示为这三者之间的关系示意图。
53
5.4 类的继承和多态 类继承的实现 1.创建子类 在Java语言中,所有的类都是由Object类派生出来的,比如前面介绍的Math类和String类,以及用户自己新建的类。 通过在类的声明中加入extends关键字来创建一个类的子类,其形式如下: [修饰符] class 子类类名 extends 父类类名 { 语句体 } 把子类定义为父类的直接子类,如果父类又是某个类的子类,则子类同时也是该类的间接子类。子类可以继承其所有父类的内容。 如果没有使用extends,则该类为java.lang.Object的子类。 类继承并不改变类中变量和方法的访问权限,如果父类中的变量和方法为public、protected或者friendly,其子类中的这些变量和方法依然为public、protected或者friendly。子类不能继承父类中访问权限为private的实例变量和实例方法。
54
5.4 类的继承和多态 5.4.2 类继承的实现 2.类继承的传递性
5.4 类的继承和多态 类继承的实现 2.类继承的传递性 类继承具有传递性,也就是说子类具有其父类和父类的父类,一直到Object类的所有类的内容。比如,B类继承了A类,而C类又继承了B类,则C类包含A类和B类的所有内容。
55
5.4 类的继承和多态 super Java中除了使用this关键字,还有一个关键字super。super指的是父类,在类的继承中有重要的作用,super的常用方法如下。 1.使用super访问父类的变量或者方法 在Java语言中,有时会遇到子类中的实例变量或者实例方法与父类中的实例变量或者实例方法同名。因为子类中的实例变量或者实例方法名具有相对高的优先级,所以子类中的同名实例变量和实例方法就隐藏了父类的实例变量或者实例方法。在这种境况下,如果想要使用父类中的某个实例变量或者实例方法,就需要用到super关键字。 2.使用父类的构造方法 如果想要使用父类的构造方法,则应当使用下面的语句形式 super( 参数); 严格意义上讲,构造方法是不能继承的。例如,父类Person有一个构造方法Person( String year, String name ),不能说子类Student也自动有一个构造方法Student( String year, String name )。但是,这不并意味着子类不能调用父类的构造方法。子类在构造方法中,可用关键字super来调用父类的构造方法。
56
5.4 类的继承和多态 5.4.3 super 下面是在子类Student的构造方法中调用父类Person的构造方法。
5.4 类的继承和多态 super 下面是在子类Student的构造方法中调用父类Person的构造方法。 public Student( String year, String name, int number ) { super( year, name ); this.number = number; } 其中,super( year, name );语句表示调用父类的构造方法,并传递相应的参数。这样的用法一般在子类构造方法的参数多于父类构造方法的参数时使用,其目的是简化构造方法的语句体。 在使用super时,要注意super与this一样指的是调用对象本身,所以super不能在static环境中使用,包括类变量、类方法和static语句块。此外,在使用super()方法时,该语句必须是构造方法的第一条语句。
57
5.4 类的继承和多态 类的多态 多态是指程序的多种表现形式。除了方法的重载,子类对父类方法的覆盖或者子类对抽象父类中的抽象方法的具体定义也是类多态的一种表现形式。 所谓覆盖,是在定义子类的方法时,使用与其父类中相同的名称和参数。在执行程序时,将执行子类的方法,而覆盖父类的方法。例如: public double sum( double a, double b ) { return a + b; } 在子类中有方法名和参数都完全相同,但是语句体内容不同的方法 return a * b; 当编写应用程序,通过子类对象调用sum()方法时,只会执行子类中求积的方法,而不会执行父类中求和的方法。
58
5.5 包和访问控制符 包 Java语言中包的作用与Windows系统中的文件夹类似,它不具有任何特别的功能,只是用来存放一个或者多个类和接口的空间。使用包可以避免同名类发生冲突,使类的管理更清晰,更有条理。包可以嵌套使用,一个包中可以再有多个包,就像一个文件夹内可以含有多个子文件夹一样。 Java语言本身固有的类都是保存在各种包中的,例如:我们前面介绍过的java.awt和java.applet包。 1.定义包 在未特别指定的情况下,Java源程序属于默认包。对于默认包中的所有类都可以相互之间引用不是private修饰的变量或者方法。但是由于默认包是没有名字的,所以它不能被其他包中的类使用import语句导入,也就不能为其他的类所使用。为了解决这个问题,我们可以定义具有名字的包。定义包的形式为: package 包名;
59
5.5 包和访问控制符 包 定义包的语句必须放在整个源程序的第一行,而且前面不能有注释语句和空格。使用这个语句就可以创建具有指定名字的包,并且当前程序中的所有类都属于这个包。 当在程序中定义包后,需要在Windows系统中创建相应的文件夹。在一般情况下,默认包对应保存程序的文件夹,也就是DOS中的当前工作目录。例如:在本书中,所有默认包中的程序都保存在C:\MyJavaPrograms文件夹中。如果是新创建的包,则需要在默认包所在的文件夹中,创建一个与包名称相同的子文件夹,用来存放这个包中所含有的类程序。
60
5.5 包和访问控制符 5.5.1 包 例如,某个程序的开始部分为: package points;
5.5 包和访问控制符 包 例如,某个程序的开始部分为: package points; public class Point{ …… } 则需要创建一个名为points的文件夹,用来保存Point类程序。 如果在package语句的包名中含有符号“.”,则代表了目录分隔符,相当于DOS语句中的符号“\”。在这种情况下,需要按照包名分割的顺序,依次创建子文件夹中的子文件夹。例如: package people.person.managers; 我们需要创建一个名为people的文件夹,然后在其中在创建person文件夹,最后在person文件夹中创建managers文件夹,而程序则要保存在managers文件夹中。
61
5.5 包和访问控制符 5.5.1 包 2.导入包 当需要使用另一个包中的类时,需要先导入该包,导入的形式为: import 包名.类名;
5.5 包和访问控制符 包 2.导入包 当需要使用另一个包中的类时,需要先导入该包,导入的形式为: import 包名.类名; 其中,包名可以使用符号“.”来表明包的层次,如果要从一个包中引入多个类,则可以用符号“*”来代替类名。例如: import java.awt.*; import people.person.*; 因为符号“*”只能表示本层次包中的所有类,不包括其子层次包中的类。所以必须多次使用import语句导入所有需要的类。例如,经常需要用两条import语句来引入两个层次的类: import java.awt.event.*; 在编译Java程序时,系统会自动为程序导入java.lang包,因此不必用import语句导入其包含的所有类。
62
5.5 包和访问控制符 常见系统包 Java语言本身固有的类,被保存在若干个包中,这些包就是我们前面介绍过的API。API是应用程序接口的英文名称Application Program Interface的缩写。所有API中的包都以“java.”开头,以便区别用户自行创建的包。下面介绍API中一些常用的包: (1)java.lang包。java.lang包提供了在编写Java程序时所需要的最基本的类。例如:各种普通数据类型的类、Math类、String类、System类和Pachage类等等。在所有这些类中,最主要的是Object类,它是所有其他类的父类。 (2)java.applet包。java.applet包是提供了用来创建Applet的必须类,它仅包含少量几个接口和一个非常有用的类:java.applet.Applet。该类用来与Applet中的组件进行交流。 (3)java.awt包。java.awt包是Java语言用来构建图形用户界面(GUI)的类库,它包括了所有创建用户界面所要使用的类,以及绘制图形和编辑图片所需要的类。例如:Button类、Label类和TextField类等。
63
5.5 包和访问控制符 常见系统包 (4)java.awt.event包。java.awt.event包提供了用来控制不同类型的事件的类和接口,并使每个图形界面的组件本身可以拥有处理它上面事件的能力。例如:ActionListener接口、ActionEvent类等等。 (5)java.io包。java.io包提供了系统输入和输出数据流时所需要的类。例如:BufferedReader类、BufferedWriter类、FileInputStream类和FileOutputStream类。 (6)java.until包。java.until包提供了Java语言中一些实用的类。例如:处理时间的Date类和Timer类,处理数组的Arrays类和Vector类。 (7)java.awt.image包。java.awt.image包提供用来创建和编辑图片的类。 (8)java.net包。java.net包提供用来实现网络功能的类。例如:Socket类和ServerSocket类等等。 (9)java.sql包。java.sql包提供了可以访问和处理保存在数据库中的数据的类。可以通过传递SQL语句来读取、写入数据以及管理数据库。 如果想要更进一步了解Java API,可以访问以下网址:
64
5.5 包和访问控制符 5.5.3 访问控制符 访问控制符是用来控制类、变量和方法的访问权限的。下面将系统全面的介绍常用的4个访问控制符。
5.5 包和访问控制符 访问控制符 访问控制符是用来控制类、变量和方法的访问权限的。下面将系统全面的介绍常用的4个访问控制符。 (1)public修饰符。类的修饰符一般为public,这表示该类为公共类,可以被所有的其他类访问和使用。当然,这并不表明类中的变量和方法也都是公共的。不过只有在类为public的条件下,我们才可以定义其中的变量和方法为public。 用public修饰的变量称为公共变量,它可以被其他所有的类调用。public修饰符会造成安全性和数据封装性下降,所以一般应减少public变量的使用,而改用访问方法来读取和写入变量数据。 用public修饰的方法称为公共方法,它可以被其他所有的类调用。 public的使用形式为: public class 类名{ …… } public 变量名; public 方法名称( 参数 ){ …… }
65
5.5 包和访问控制符 访问控制符 (2)protected修饰符。使用protected修饰的变量和方法,可以被同一个包中的其他类、类本身以及类的子类访问和调用。子类既可以是在同一个包中的类,也可以是在不同包中的类。 protected的使用形式为: protected 变量名; protected 方法名称( 参数 ){ …… } (3)private修饰符。使用private修饰的变量和方法,只可以被类本身访问和调用。同一个类的不同对象可以互相访问对方的private实例变量或者调用对方的private实例方法,这是因为访问控制符是在类级别上的,而不是对象级别上的。 此外,如果限定构造方法为private,则其他类不能生成该类的一个对象实例。 private的使用形式为: private 变量名; private 方法名称( 参数 ){ …… }
66
5.5 包和访问控制符 访问控制符 (4)friendly修饰符。friendly修饰符是Java语言默认的修饰符。当一个变量或者方法没有任何修饰符修饰时,系统默认其修饰符为friendly。使用friendly修饰的变量和方法,可以被同一包中的其他类和类本身访问和调用。如果类没有修饰符,则表示该类只可以被同一包中的其他类访问和使用。 除了上面介绍的4个修饰符外,还有private protected修饰符,也叫私有保护访问控制符。其中private和protected的位置不可以调换。使用private protected修饰符修饰的变量和方法可以被该类本身和其子类所访问和调用。其中,子类既可以是在同一个包中的类,也可以是在不同包中的类。相对于protected修饰符,private protected修饰符把同一包内的非子类排除在可以访问的范围之外,使得变量和方法专用于具有明确继承关系的类中。
67
5.6 接口 接口的概念 Java语言中,一个子类只可以继承一个直接父类,这被称为单一继承。使用单一继承虽然各个类之间的层次关系清楚、可读性强,但是在处理一些复杂问题时,则会显得功能不够强大。因此,Java语言提供了接口功能,来实现多重继承。接口是用来组织类内容的一种程序结构,一个类可以有多个接口。 在驾驶汽车时,驾驶员只需要知道使用离合器来换档、使用加速器和车闸来调整行使速度即可,不需要知道这些操作的具体执行过程。同样地,在Java语言中我们也经常不需要了解某些对象的具体结构,只要知道如何使用即可。例如:我们在调用int、Math和String等类的方法时,并不需要知道它们的实现过程。 在Java语言中,一个对象的行为一般是与其具体的实现细节分开的。也就是说,在开发程序时,一方面,我们可以在不了解某个对象的具体实现细节的情况下,使用该对象;另一方面,我们可以在不知道对象将被如何应用的情况下,编写其功能的具体实现细节。这种对象行为与行为的具体实现细节分离的设计方法称为抽象。
68
5.6 接口 接口的概念 抽象的数据结构只定义对象所支持的操作,而不具体描述这些操作是如何实现的。在Java语言中,使用接口来定义某个类所支持的操作。因此,在接口中,所有的方法均为抽象方法。接口定义的仅仅是实现某一特定功能的接口和其规范,而并没有真正实现这个功能。这个功能的真正实现是在应用这个接口的类中完成的,要由类来具体定义接口中各个抽象方法的语句体。 例如:如果我们定义了一个名为Calculate的接口,其中有add()和minus()两个抽象方法,那么任何实现该接口的类都必须支持其中的add()和minus()方法,也就是说在类中具体描述这两个方法的语句体内容。 总的来说,Java语言通过接口使得处于不同层次、互不相关的类可以具有相同的行为。而且接口可以弥补由于类的单一继承所产生的功能不足。这样就可以既保留类的单一继承所带来的程序简洁和层次清晰等方面的好处,还可以再拥有多个接口提供的强大功能。
69
5.6 接口 5.6.2 接口的实现 创建接口的形式如下。 public interface 接口名 {
5.6 接口 接口的实现 创建接口的形式如下。 public interface 接口名 { public static final 变量名 = 常量数据; public abstract 方法类型 方法名( 参数 ); } 其中,关键字interface是用来定义接口的,接口名要符合Java对标识符的规定,public是接口的唯一访问控制修饰符。如果没有使用任何访问控制修饰符,则表示只有与该接口定义在同一个包中的类才可以访问这个接口。接口中的变量只能是常量形式的变量,方法也必须是抽象方法。因为接口中的方法均是使用修饰符public和关键字abstract修饰的,所以在书写时可以省略这两个单词。
70
5.6 接口 5.6.2 接口的实现 例如:在下面的接口程序中,我们定义了2个常量和3个抽象方法。 interface Calculate
5.6 接口 接口的实现 例如:在下面的接口程序中,我们定义了2个常量和3个抽象方法。 interface Calculate { int i = 10; String s = "计算结果如下。" boolean isZhishu(); int add( int a, int b ); double minus( int a, int b ); } 创建接口仅仅给出了抽象方法,如果要具体的实现接口所定义的方法,则需要某个类为接口中的每个抽象方法定义具体的操作来实现这个接口的功能。
71
5.6 接口 5.6.2 接口的实现 实现接口的形式为: public class 类名 implements 接口名1, 接口名2, ……
5.6 接口 接口的实现 实现接口的形式为: public class 类名 implements 接口名1, 接口名2, …… { 语句体 } 其中,使用关键字implements来定义这个类的接口,一个类可以实现多个接口,使用逗号将它们分隔开。 如果实现某个接口的类不是使用关键字abstract修饰的抽象类,则在类中必须定义实现接口所有抽象方法的具体实例方法,并且该方法必须与接口中的方法定义完全一致,也就是说具有完全相同的参数个数和类型,以及方法的返回类型。
72
5.6 接口 接口的实现 如果实现某个接口的类是使用关键字abstract修饰的抽象类,则它可以不实现该接口所有的方法。但是在这个抽象类的任何一个非抽象子类中,必须具体定义其父类所实现的接口中的所有抽象方法。 因为接口的抽象方法的访问控制符均为public,所以类在实现这些抽象方法时,必须使用public修饰符,否则系统将显示缩小了接口中定义的方法的访问控制范围的提示。例如:下面的程序是一个简单的接口和实现其的类。 public interface Num { int num = 10; public void printNum(); } public class TestNum implements Num public void printNum() System.out.println( "Num=" + Num );
73
5.6 接口 5.6.3 抽象类和抽象方法 抽象类的意义与接口基本一样,都是为了更好的控制类的抽象结构。定义抽象类的形式为:
5.6 接口 抽象类和抽象方法 抽象类的意义与接口基本一样,都是为了更好的控制类的抽象结构。定义抽象类的形式为: abstract class 类名 { 语句体 } 抽象类中的方法可以是实例方法,也可以抽象方法。但是如果一个类含有抽象方法,则此类必须为抽象类。而其如果一个类是抽象类的子类且其不是抽象类,则该子类必须实现父类的所有抽象方法。 抽象方法定义了一个抽象类的功能,但是没有给出该功能的具体实现过程。定义抽象方法的形式为: abstract 方法类型 方法名( 参数 ); 抽象方法不能使用修饰符static和final修饰。
Similar presentations