1、第四章第四章 面向对象(上)面向对象(上)l什么是抽象什么是抽象 l类与对象及其关系类与对象及其关系 l类中定义的属性(域)与方法(操作)类中定义的属性(域)与方法(操作)l对象对象 l构造方法构造方法 l类成员属性和方法的其它修饰符类成员属性和方法的其它修饰符l包(包(Package)主要内容主要内容什么是抽象抽象的定义抽象的定义l抽象(abstraction)是从被研究对象中舍弃个别的、)是从被研究对象中舍弃个别的、非本质的、或与研究主旨无关的次要特征,而抽取与非本质的、或与研究主旨无关的次要特征,而抽取与研究有关的共性内容加以考察,形成对研究问题正确研究有关的共性内容加以考察,形成对研究
2、问题正确的简明扼要的认识。的简明扼要的认识。动物动物经过人类抽象用一个叫”动物”的类来概括类与对象及其关系 类与对象及其关系类与对象及其关系 l对象是对客观事物的抽象。对象是对客观事物的抽象。l类是对对象的抽象,在语言中是一种抽象的数据类是对对象的抽象,在语言中是一种抽象的数据类型。类型。l类的定义在类的定义在Java中可简述为中可简述为 l class 类名类名 l它们的关系是,对象是类的实例,类是对象的模它们的关系是,对象是类的实例,类是对象的模板。板。类中定义的属性与方法 类中定义的属性(域)与方法(操作)类中定义的属性(域)与方法(操作)类和对象都有属性和操作,属性是事物静态特征的抽象
3、,操作是事物动态特征的抽象。如【例4.1】class FighterPlane String name;int missileNum;void fire()if(missileNum0)missileNum-=1;System.out.println(“now fire a missile!”);else System.out.println(“No missile left!”);类的属性或称为“域”类的方法类中的域变量和方法存在以下关系类中的域变量和方法存在以下关系类中定义的域变量可以被类中所有的方法所访问。方法中的形式参数和定义的局部变量的作用域仅限 于方法,局部变量在使用前必须进行赋值
4、初始化。如果局部变量和类中的属性变量重名,则在方法中 对同名变量改变的是局部变量。类中定义的方法可以进行递归调用【例4.2】Java的类的类 一个一个Java类形式上包含两个部分:类形式上包含两个部分:类首说明 类体 类首说明 类首说明的形式如下:类首说明的形式如下:修饰符 class 类名 extends超类名 implements接口名列表 类的修饰符有类的修饰符有private、public、abstract、final。一个类可以同时有多个修。一个类可以同时有多个修饰符,但是不能有相同的修饰符。当一个类有多个修饰符时,这些修饰符无饰符,但是不能有相同的修饰符。当一个类有多个修饰符时,这
5、些修饰符无先后顺序之分,可以任意的顺序排列它们。先后顺序之分,可以任意的顺序排列它们。注意:abstract和和final不能同时作为一个类的修饰符。不能同时作为一个类的修饰符。private(私有私有):修饰的类只能被同一包名中的类访问,这是修饰的类只能被同一包名中的类访问,这是Java默认方式;默认方式;public(公共公共):修饰的类能被所有的类访问;修饰的类能被所有的类访问;abstract(抽象抽象):修饰的类修饰的类不能被实例化,它包含有未实现的方法。,它包含有未实现的方法。final(最终最终):修饰的类不能被继承,即修饰的类不能被继承,即不能有子类。类名是所创建的类的名字,类
6、名可以是任意的类名是所创建的类的名字,类名可以是任意的Java标识符,根据标识符,根据Java命命名的约定,类名的每个有意义的单词的首字母要大写,其余字母小写。名的约定,类名的每个有意义的单词的首字母要大写,其余字母小写。extends(继承继承):保留字用来表明新创建的类继承哪个类,被继承的类称为保留字用来表明新创建的类继承哪个类,被继承的类称为此类的超类。此类的超类。extends后面只能跟一个超类名称。后面只能跟一个超类名称。implements(实现实现):用来表明这个类实现了哪些接口,接口名可以有多个。用来表明这个类实现了哪些接口,接口名可以有多个。类体 类体中定义了该类所有的成员变
7、量和该类所支持的方法,其形式说明类体中定义了该类所有的成员变量和该类所支持的方法,其形式说明如下:如下:类体 成员变量说明 构造方法说明 静态初始化说明 方法说明 类体由成员变量说明、构造方法说明、静态初始化说明和方法说明构类体由成员变量说明、构造方法说明、静态初始化说明和方法说明构成,它们都是可选的。类体中的这四种说明没有先后顺序之分,但是成,它们都是可选的。类体中的这四种说明没有先后顺序之分,但是为了类的可读性,建议按照上面出现的顺序说明。为了类的可读性,建议按照上面出现的顺序说明。成员变量说明及其使用成员变量说明及其使用 1成员变量说明 成员变量的说明类似于方法的局部变量说明,所不同成员
8、变量的说明类似于方法的局部变量说明,所不同的是,成员变量定义在类中,是类成员的一部分,整的是,成员变量定义在类中,是类成员的一部分,整个类都可以访问它。个类都可以访问它。Java中成员变量说明形式如下:中成员变量说明形式如下:修饰符修饰符 成员变量类型成员变量类型 成员变量名列表成员变量名列表;成员变量的修饰符有以下几种:缺省访问修饰符、成员变量的修饰符有以下几种:缺省访问修饰符、public、protected、private、final、static、transient和和volatile。(1)缺省访问修饰符 缺省访问修饰符的成员变量可以被同一包(缺省访问修饰符的成员变量可以被同一包(p
9、ackage)中的任何类访问。)中的任何类访问。(2)public(公共)public修饰的成员变量可以被项目文件中的任何方法所访问。由于修饰的成员变量可以被项目文件中的任何方法所访问。由于public成员变量不成员变量不受限制受限制,这易使类的对象引起不希望的修改,建议成员变量尽量不要使用这易使类的对象引起不希望的修改,建议成员变量尽量不要使用public修饰符。修饰符。(3)protected(受保护)protected修饰的成员变量可以被有继承关系的类自由访问,即子类可以访问它。修饰的成员变量可以被有继承关系的类自由访问,即子类可以访问它。(4)private(私有)private修饰的
10、成员变量只能在同一个类中使用。这种方式通常是最为安全的。修饰的成员变量只能在同一个类中使用。这种方式通常是最为安全的。(5)static(静态):(类变量)(类变量)static修饰的成员变量又称为类变量。不加修饰的成员变量又称为类变量。不加static修饰的成员变量又叫对象变量。修饰的成员变量又叫对象变量。对象对象变量依附于具体的对象实例,它的值因具体对象实例的不同而不同,而类变量为该类变量依附于具体的对象实例,它的值因具体对象实例的不同而不同,而类变量为该类的所有对象共享,它的值不因类的对象不同而不同。的所有对象共享,它的值不因类的对象不同而不同。(6)final(最终):(常量)(常量)
11、final修饰的成员变量叫最终成员变量。一开始创建该变量时将其设定了一个值,在以修饰的成员变量叫最终成员变量。一开始创建该变量时将其设定了一个值,在以后程序的运行过程当中,变量的值将一直保持这个值不变。最终变量又称为常量。后程序的运行过程当中,变量的值将一直保持这个值不变。最终变量又称为常量。Java中的常量必须是类的成员。对于最终成员变量,任何赋值都将导致编译错误。因中的常量必须是类的成员。对于最终成员变量,任何赋值都将导致编译错误。因为常量在说明以后就不能改变其值,所以常量必须要使用变量初始化来赋初值。无论为常量在说明以后就不能改变其值,所以常量必须要使用变量初始化来赋初值。无论是实例变量
12、,还是类变量,都可以被说明成常量。是实例变量,还是类变量,都可以被说明成常量。final修饰符和修饰符和static修饰符并不冲突。修饰符并不冲突。成员变量类型可以是基本类型或类。成员变量名使用符合成员变量类型可以是基本类型或类。成员变量名使用符合Java规定的标识符来表示。规定的标识符来表示。成员变量使用 类的成员变量在定义它的类内部,直接通过类的成员变量在定义它的类内部,直接通过成员变量名来访问。如从类的外部访问,类变量和类来访问。如从类的外部访问,类变量和类对象变量的使用方法是不同。使用类变量的格式对象变量的使用方法是不同。使用类变量的格式如下:如下:类名.类变量名 由此可见,访问类变量
13、与类的对象构造和对象都无关。由此可见,访问类变量与类的对象构造和对象都无关。访问类对象变量的格式如下:访问类对象变量的格式如下:类对象名.类对象变量名 由此可见,要使用对象变量首先要构造对象,获得类由此可见,要使用对象变量首先要构造对象,获得类对象名。类对象名即对应的类变量名。对象名。类对象名即对应的类变量名。例例4-1 成员变量的访问成员变量的访问 class Point final static Point origin=new Point(0,0);/定义一个类变量,常量,定义一个类变量,常量,origin为坐标原点为坐标原点 int x;int y;Point(int x,int y)
14、thisx=x;this.y=y;public class UsingStatic public static void main(String args)Point p1=Point(10,20);/构造类构造类Point的对象的对象p1 Point p2=Point(310,120);System.out.println(类类Point中的类变量:中的类变量:);System.out.println(+Point.origin.x+,+Point.origin.y+);/访问类变量访问类变量(类名.类变量名)System.out.println(类类Point中的类实例变量:中的类实例变量
15、:);System.out.println(+p1.x+,+p1.y+);/访问类对象变量访问类对象变量x、y,p是类对象名是类对象名(类对象名.类对象变量名)迪米特法则迪米特法则 Law of Demeter 1987,Northeastern University 火星登陆软件,木星欧罗巴卫星轨道飞船软件系统火星登陆软件,木星欧罗巴卫星轨道飞船软件系统 Dont talk to strangers对 象对象的产生对象的产生 String name;int missileNum;void firevoid fire()()F F ighterPlaneighterPlaneNEWNEW类对象
16、String name;int missileNum;void firevoid fire()()F F ighterPlaneighterPlane对象的产生使用的代码:对象的产生使用的代码:new FighterPlane();对象的声明使用的代码:对象的声明使用的代码:FighterPlane fp;String name;int missileNum;v vo oi id d f fi ir re e()F F i ig gh ht te er rP Pl la an ne eNEW类对象String name;int missileNum;v vo oi id d f fi ir r
17、e e()F F i ig gh ht te er rP Pl la an ne ef fp p可以声明后立即赋予对象:可以声明后立即赋予对象:FighterPlane fp =new FighterPlane()对象内存空间分布对象内存空间分布当“FighterPlane fp =new FighterPlane()”处于某个方法中时:对象作为参数的特点对象作为参数的特点 普通数据类型作为参数传递是值传递,普通数据类型作为参数传递是值传递,【例例4.3】。对象是引用传递对象是引用传递。a对象s对象as【例例4.4】【例例4.5】对象数组对象数组MyClass mc=new MyClass10
18、;数组对象特点及常用方法数组对象特点及常用方法l具有对象引用的特点,例具有对象引用的特点,例【4.64.6】l属性属性lengthlength的用法,例的用法,例【4.74.7】构造方法构造方法的含义,构造方法的含义,【例例4.84.8】构造方法的特征,构造方法的特征,【例例4.94.9】、【4.104.10】构造方法的注意事项构造方法的注意事项 finalizefinalize方法与垃圾回收方法与垃圾回收 什么是垃圾对象?垃圾对象何时回收?垃圾对象回收时调用finalize方法。构造方法说明 每当由类构造对象时都要调用该类特定的构造方法,在每当由类构造对象时都要调用该类特定的构造方法,在Ja
19、va中,每个类都至中,每个类都至少有一个构造方法。构造方法可以确保用户正确地构造类的对象,同时,构少有一个构造方法。构造方法可以确保用户正确地构造类的对象,同时,构造方法也会对对象作初始化工作。构造方法说明形式如下:造方法也会对对象作初始化工作。构造方法说明形式如下:构造方法修饰符 方法名(形式参数列表)throws异常列表 方法体 构造方法修饰符与一般方法修饰符相同,读者参见构造方法修饰符与一般方法修饰符相同,读者参见4.3.3小节。小节。构造方法不能像一般的方法那样被直接调用,它是在构造类的实例的时候被构造方法不能像一般的方法那样被直接调用,它是在构造类的实例的时候被Java编译器自动调用
20、的。当我们构造一个类的实例的时候,编译器主要完成编译器自动调用的。当我们构造一个类的实例的时候,编译器主要完成以下三件事情:以下三件事情:(1)为对象分配内存空间;为对象分配内存空间;(2)初始化对象中的实例变量的值,初始值可以是缺省值,或者变量按指定的初始化对象中的实例变量的值,初始值可以是缺省值,或者变量按指定的值初始化;值初始化;(3)调用对象的构造方法。调用对象的构造方法。一个类的构造方法可以有多个,它们都具有相同的方法名,即类名。编译器一个类的构造方法可以有多个,它们都具有相同的方法名,即类名。编译器根据参数的类型来决定调用哪个构造方法。构造方法分为缺省的构造方法根据参数的类型来决定
21、调用哪个构造方法。构造方法分为缺省的构造方法(不带参数)和带参数的构造方法。(不带参数)和带参数的构造方法。缺省的构造方法 如果类的定义没有编制构造方法,如果类的定义没有编制构造方法,Java语言会自动为用语言会自动为用户提供。这个由户提供。这个由Java自动提供的构造方法就是所谓的缺自动提供的构造方法就是所谓的缺省构造方法。缺省的构造方法确保每个省构造方法。缺省的构造方法确保每个Java类都至少有类都至少有一个构造方法,该方法应符合类的定义。一个构造方法,该方法应符合类的定义。例如在例例如在例4-1的类的类Point中,如果我们没有定义构造方法,中,如果我们没有定义构造方法,则则Java自动
22、提供了一个缺省的构造方法,如下:自动提供了一个缺省的构造方法,如下:缺省的构造方法:public Point();/对象成员变量的初值按Java规定 带参数的构造方法 带有参数的构造方法能够实现这样的功能:当构造一个新带有参数的构造方法能够实现这样的功能:当构造一个新对象时,类构造方法可以按需要将一些指定的参数传递给对象时,类构造方法可以按需要将一些指定的参数传递给构造方法。构造方法。如:如:public Point(int x,int y)this.x=x;this.y=y;类成员属性和方法的非访问修饰符方法说明 在在Java中,方法总是中,方法总是Java类的一个组成部分。类的一个组成部分
23、。通过类的方法,改变对象的状态。方法说明的格式如下:。方法说明的格式如下:方法首部说明 方法体 方法说明分为方法首部说明和方法体两部分。方法说明分为方法首部说明和方法体两部分。方法修饰符包括以下几种:包括以下几种:public 修饰的方法可以由其他类访问;修饰的方法可以由其他类访问;protected 修饰的方法只能由继承关系的类访问;修饰的方法只能由继承关系的类访问;private 修饰的方法只能由说明该方法的类访问;修饰的方法只能由说明该方法的类访问;static 修饰的方法为静态方法,又叫类方法修饰的方法为静态方法,又叫类方法;无无static修饰的方法为对象方法。修饰的方法为对象方法。
24、类方法是该类的所有类方法是该类的所有对象共享的方法。对象共享的方法。abstract 修饰的方法为抽象方法,无其方法体;修饰的方法为抽象方法,无其方法体;final 修饰的方法为最终方法,不能由子类改变;修饰的方法为最终方法,不能由子类改变;synchronized(同步同步)修饰的方法执行之前给方法设修饰的方法执行之前给方法设置同步机制,实现线程同步;置同步机制,实现线程同步;native 修饰的方法为本地方法修饰的方法为本地方法,即方法实现与本即方法实现与本机系统有关。机系统有关。方法名是方法名是Java中任意的标识符。按照命名的约定,中任意的标识符。按照命名的约定,方法名应该是有意义的动
25、词或动词短语,它的第一方法名应该是有意义的动词或动词短语,它的第一个字母一般要小写,其他有意义的单词的首字母要个字母一般要小写,其他有意义的单词的首字母要大写,其余字母小写。返回值类型可以是任意的大写,其余字母小写。返回值类型可以是任意的Java类型,甚至可以是定义此方法的类。如果方法类型,甚至可以是定义此方法的类。如果方法没有返回值,则用没有返回值,则用void表示。表示。形式参数列表是可选的。如果方法没有形式参数,是可选的。如果方法没有形式参数,就用一对小括号就用一对小括号“()”表示。形式参数列表的形式如表示。形式参数列表的形式如下:下:(类型 形参名,类型 形参名,)throws异常列
26、表规定了在方法执行中可能导致的异规定了在方法执行中可能导致的异常。第常。第5章会详细介绍。章会详细介绍。4.3.3.2方法体方法体 方法体是实现这个方法的代码段,它由方法体是实现这个方法的代码段,它由“”和和“”括起来的语句序列构成。方法体也可以是括起来的语句序列构成。方法体也可以是一个分号一个分号“;”,表示无方法体,该类没有实,表示无方法体,该类没有实现。当且仅当方法的修饰符中有现。当且仅当方法的修饰符中有abstract或或native时,方法才无方法体。时,方法才无方法体。方法的调用方法的调用 类方法调用形式如下:类方法调用形式如下:类名.类静态方法名(实参列表)对象方法调用形式如下:
27、对象方法调用形式如下:类对象名.类非静态方法名(实参列表)前面的例子中经常使用到类方法,应用程序中的主方法前面的例子中经常使用到类方法,应用程序中的主方法main就是类方法。类方法和类变量一样,都是对整个类而就是类方法。类方法和类变量一样,都是对整个类而言的,而不是针对类的对象。一些通用的、公用型的方法言的,而不是针对类的对象。一些通用的、公用型的方法不能直接作用在类的对象,因此常常被作为类方法实现。不能直接作用在类的对象,因此常常被作为类方法实现。Java类库中类库中Math类,其中多数的数学运算的操作都被定义类,其中多数的数学运算的操作都被定义成静态方法。因此,一些通用的、公用型的方法可以
28、使用成静态方法。因此,一些通用的、公用型的方法可以使用类方法把它们放在合适的类中,从而很好地将它们组织起类方法把它们放在合适的类中,从而很好地将它们组织起来。来。关于类方法的使用,有如下一些限制:关于类方法的使用,有如下一些限制:(1)在类方法中不能引用对象变量。在类方法中不能引用对象变量。(2)在类方法中不能使用在类方法中不能使用super、this关键字关键字(super、this介绍见介绍见后后)。(3)类方法不能调用类中的对象方法。类方法不能调用类中的对象方法。如果违反这些限制,你的程序就会导致编译错误。如果违反这些限制,你的程序就会导致编译错误。与类方法相比,对象方法几乎没有什么限制
29、:与类方法相比,对象方法几乎没有什么限制:(1)对象方法可以引用对象变量(这是显然的),也可以引用类变对象方法可以引用对象变量(这是显然的),也可以引用类变量(甚至一个对象变量都不引用)。量(甚至一个对象变量都不引用)。(2)对象方法中可以使用对象方法中可以使用supper、this关键字。关键字。(3)对象方法中可以调用类方法。对象方法中可以调用类方法。如果包含类方法的类被继承,那么其子类中既可以使用带有超类如果包含类方法的类被继承,那么其子类中既可以使用带有超类名的限定名来访问该类方法,也可以使用子类名的限定名来访问名的限定名来访问该类方法,也可以使用子类名的限定名来访问该类方法。该类方法
30、。static 用用static修饰符修饰的数据成员是不属于任何一个类的具修饰符修饰的数据成员是不属于任何一个类的具体对象,而是属于类的静态数据成员。体对象,而是属于类的静态数据成员。它被保存在类的内存区的公共存储单元中它被保存在类的内存区的公共存储单元中,而不是保存在而不是保存在某个对象的内存区中。因此某个对象的内存区中。因此,一个类的任何对象访问它时,一个类的任何对象访问它时,存取到的都是相同的数值。存取到的都是相同的数值。访问方式为通过类名加点操作符来访问,也可通过对象引访问方式为通过类名加点操作符来访问,也可通过对象引用来访问。用来访问。Static修饰的方法有如下特点:修饰的方法有如
31、下特点:lstatic方法是类方法,但可以被所有对象所访问,方法是类方法,但可以被所有对象所访问,引用这个方法时,可以使用对象名做前缀,也可引用这个方法时,可以使用对象名做前缀,也可以使用类名做前缀。以使用类名做前缀。lstatic方法内部的代码,只能访问类中的方法内部的代码,只能访问类中的static属属性或方法,不能访问类中的非性或方法,不能访问类中的非static属性或方法属性或方法(因为那是对象方法),但非(因为那是对象方法),但非static方法(对象方法(对象方法)可以访问方法)可以访问static数据成员。数据成员。lmain方法是特殊的静态方法,是方法是特殊的静态方法,是App
32、lication程程序入口点,必须写成序入口点,必须写成public static void main(String args)的形式。的形式。final final修饰属性,则属性为常量(全部大写);修饰属性,则属性为常量(全部大写);如果修饰方法,则方法称为最终方法,在子类如果修饰方法,则方法称为最终方法,在子类当中不能被覆盖,可防止任何继承类修改此方当中不能被覆盖,可防止任何继承类修改此方法。法。abstract与与native 包(Package)包(包(Package)随着Java的应用,SUN公司的JDK,各系统开发商,以及自己开发的类越来越多,如何对这些类进行有效的组织管理和有效使用,Java的解决办法是“包”。