Java语言的面向对象编程_第1页
Java语言的面向对象编程_第2页
Java语言的面向对象编程_第3页
Java语言的面向对象编程_第4页
Java语言的面向对象编程_第5页
已阅读5页,还剩34页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第三章 面向对象的编程理论本章导读在本章中,我们将讨论Java语言的面向对象的特征。正如前面所介绍的,Java语言是一种标准的面向对象的编程语言,它具具的面向对象的特征非常强大,使用非常方便,同时,其语言本身又具有C+语言的灵活性。这也是我们推广Java语言的原因之一。接口是Java语言中非常重要的概念,由于Java不支持多继承,因此引入了接口的概念,用来完成多继承的一些功能,同时接口还是面向对象一个重要思想设计与实现的分离的体现。使用接口进行设计,然后通过类来实现这些接口,这是一种非常高效的编程方式。在本章介绍接口的时候,我们首先介绍抽象类和抽象方法,它们提供了一定程度的抽象,也体现了设计与

2、实现的分离。接口比抽象类和抽象方法提供了更高层次的抽象。包是Java语言中引入的另一个重要概念。包使得类库的组织更加条理,包还可以提供一定程度的封装和访问控制。Java语言中很多访问控制都限制在包的层次上。本章的内容既多又繁杂,在介绍一种新的概念时,我们重点从两方面进行介绍,一是关于概念的理解,介绍的方式是将很多Java语言中的术语与现实生活中的一些术语对应起来;二是关于概念的应用,介绍的方法是通过规则描述和举例的方式进行。我们希望这样做,既能使您在语法上有清晰的认识,又能使您准确地把握概念的内涵,并且能够在编程中熟练的使用,使您真正掌握面向对象的编程理论。本章内容面向对象的理论、概念。Jav

3、a语言中的类和对象的定义。类定义、属性定义、方法定义。继承的概念,以及由此引出的方法和属性的继承、隐藏、覆盖。接口定义/包定义。如何创建接口与包,如何访问包中的类和接口。关于类、抽象类、接口的使用原则。学习目标掌握面向对象的理论知识。学会类的定义,类实例化的方法。学会接口、包的定义。学会用面向对象的理论编程。3.1面向对象的编程理论“面向对象”是近年来IT行业非常流行的概念。在现实世界中,可能用的更多的是“对象”这个名词,对象的概念很难定义,但我们都理解其所具有的含义。按照正规的定义,对象是指行动或思考时作为目标的人或事物,强调的是把对象作为一个独立、完整的目标来对待,这也是IT行业引用对象这

4、个概念的初衷。在介绍面向对象的编程理论之前,首先介绍一个已经使用几十年的结构化编程理论。结构化编程的思想强调的是一个系统由一个个独立的、较小的功能组成。随着软件系统的规模越来越大,这种编程理论遇到了较大的挑战,一个系统可能由成千上万个功能组成,而且它们之间相互调用,设计起来很难理顺它们的关系,在维护时,更会造成一动而引发全身的系列行为,大大增加了维护的难度。为了克服结构化编程的缺点,人们在设计和实现一个系统时,开始把分析一个系统的视角由一个个功能转移到系统所包含的对象上来。如对一个人事管理信息系统,它所处理的对象包括一个单位不同部门的人员,每个部门的人员可能具有不同的特点和分工,如行政人员强调

5、的是行政级别,开展的是一些管理工作;技术级别强调的是技术职称,开展的是一个技术研究工作等等。他们的有些工作是共性的,如完成年度总结,但大部分工作是与他们的分工相关的,如果我们在设计一个系统时,能够将一些功能与完成这些功能的人对应起来,并把人与事放在一起管理,在出现一些功能变化时,我们只须针对与之相关的方面进行调整即可,这就是面向对象的设计思想。在现代软件工程设计中,面向对象的思想在软件设计和软件编程方面得到了深入的应用。面向对象的内容很丰富,要想全面的了解面向的对象的程序设计方法,您可能需要花上几年的时间。在本书中,我们只介绍一些与编程有关的、基础性的一些概念。面向对象的分析方法可以说是方法论

6、中的一个新理论,在社会学理论中也有非常重要的意义,尤其是在管理理论方面,应用的非常广泛,如目标管理关注的就是结果,而对实现的过程关不关心,这和面向对象的理论是一致的。面向对象的理论来源我我们对现实世界的认识过程。现实世界就是由各种各样的有形或无形的事与物构成的,人们通过判断这事物的基本特征,识别出不同的事物,例如,我们通过花纹和大小,能够分辩出足球与篮球;我们通过社会不同的不同,将所有人分成工人、农民、军人等,他们从事的工作有很大差别。有的事物在宇宙中只有一个,有的可能有千千万万,这种数量上的差别也会随着我们分析事物的视角不同而不同,例如,太阳只有一个,但但它只是无数恒星中的一员。我们常常把这

7、种具有相同特征的事与物划分成 “类”来表示,典型的例子就是我们人类,每一个人都具有人类一些共性,如一个鼻子,两只眼睛等等,但世界上不同的民族又具有各自的特征,如黄种人的头发是黑的,欧洲人的头发是黄的等等。从性别上又可分为男人和女人,从年龄上可分为幼儿、少年、青年、中年、老年,从性格上分可分为内向型的和外向型的等等。正是这些丰富的特征构成了丰富的人类社会。面向对象的分析(OOD,Object Oriented Design)和面向对象编程(OOP,Object Oriented Programming)就是从我们认识世界的方法中提炼出来,并应用到软件工程中的一项革命性的软件开发理论,成为二十世纪

8、八十年代以来的最主流的软件工程方法之一。我们对事物的分析一般有两个视角,一个是个体特征,另一个是群体特征,所谓个体,就是指一个具体的物或事,例如我们班上的张三,是全班学生中的一员。所谓群体,就是指具有共同特征的个体的总称,例如我们现在所在的班级全体学生。通过描述群体成员中的具体特征,我们可以定位到每一个个体,如我们可以通过姓名从全班学生中找到叫张三的人。我们在分析群体时,往往是强调的是群体中所有个体均具有的共同特征,如通过篮球的生产厂家确定某某品牌的篮球质量好,这就将某某品牌的篮球确定为一类。在JAVA语言中,我们首先定义一个群体,也就是类,再由它确定一个个个体,也就是对象或称为实例。类和对象

9、的概念是面向对象程序设计的核心,这两个概念既基础又重要。这里还需要强调的是类的共同特征问题,在我们分析一个事物时,如果一个群体与另一个群体具有明显的差异,而且我们就是在强调这种差异,那么这两个群体则不能划分为一个群体,但如果我们强调的是这两个群体的共性,那么这两个群体则有可以划分为一个大的群体,如人类有别于其它动物,如果我们分析人类的一些商业行为时,一般不会过多地分析其它动物是否也具有这样的行为,但如果我们分析人类和其它动物饮食区别时,我们又常常将人类和其它动物类统统放在动物类加以研究。我们在分析一个事物时,往往将这些事物的特征分为两类,一类在相对静止不变的特征,如太阳是圆的;一个人有姓名、出

10、生时间、性别等特征,我们称这些特征为属性;另一类是动态的特征,如太阳发光;人会走路等特征,我们称这些特征为行为,在JAVA语言中,将这些行为称为方法。同时,我们在分析一个事物时,往往采用由表及里、由外到内的认识过程,如一个人有两条腿,每条腿是由大腿、小腿和脚组成的,这样一直可以分解到细胞或分子的深度。同时在我们走路时,只有我们的大腿、小腿、脚进行有机的配合,甚至还需要我们上肢的合作,我们才能运动自由。上述分析对应在面向对象的编程过程中,只不过是将软件开发中所需要面对的对象进行归纳,形成了一个个对象的模型。现实世界中的对象不是孤立的,任何对象都要和其它的对象发生关系。比如人可以启动汽车并驾驶汽车

11、,足球运动员可以让足球以很快的速度射向球门,等等。在面向对象的编程中,对象之间也是可以相互作用的,它们通过收发消息相互联系,相互作用。一个对象如果想要求另外一个对象执行某种行为,就可以向它发送消息,接收消息的对象对消息做出响应,执行自己的某些行为。例如,有两个对象:人和汽车,如果人要启动汽车,就需要发送消息给汽车(在现实中,这种消息可能是插入钥匙并踩住油门),汽车对这个消息做出响应,执行自己的启动程序来启动汽车。收发消息是对象之间通信的一种方式,我们往往将注意力集中在这一层面上,但对发动机是如何启动的,汽车是如何被燃烧的等等细节并不关心,只要汽车能够正常启动和行驶就足够了。这也是程序设计中封装

12、这个概念的由来。通过归纳和分析,我们可以将对象定义为由属性和行为组成的封装体。并且具有如下的特点:针对性。对象的针对性是指我们在认识一个对象时,总是对应一个具体的物体或事件,它是具体的一个,而不是抽象的、无法确定的一批。对于这一点,必须有一个清楚的认识,否则会与类的概念相混淆。自治性。对象的自治性是指对象具有一定的行为能力。对于一定的消息输入,对象能够做出反应,执行一定的行为,从而改变自身的属性或者产生某种输出。封闭性。对象的封闭性是指对象包括了属性和行为,这些属性和行为的实现细节对于其它对象来说关系不太,而且在处理其它对象时,我们不必关心本对象的实现细节。关联性。对象的通信性是指对象具有和其

13、它对象通信的能力,即对象能够接收其它对象发来的消息,也能向其它对象发送消息。通信性反映了对象之间的某种联系,通过这种联系,许多对象可以协同完成某项任务。类的概念是对对象的分析总结后得出的一个重要概念,它是为描述具有相同特征的对象而引入的,在面向对象的编程中,实际的操作是首先创建类,然后再通过类创建对象即实例,再通过些实例完成业务功能。练习3-1请列出一些具有类和对象的一些例子。练习3-2对比一个类与对象这两个概念的相同点和不同点。3.2创建类前面,您已经了解了面向对象编程的一些基本的理论。在本节中,我们将向您介绍如何创建自己的类,包括类的声明、属性的声明、和方法的声明。在Java语言中,没有独

14、立于类之外的变量、属性、函数及方法。在Java语言中,类也是一种数据类型,它属于引用类型。创建一个类,就是声明了一种新的数据类型,并且定义了它是如何实现的。3.2.1类的定义在Java语言中,类的定义形式如下:修饰符 class类名 extends超类名 implements接口名 类体注意:用方括号“”括起来的部分表示是可选的,即可有可无的。class 是类定义关键字。类名是所创建的类的名字,在程序中是通过类名来引用一个类的,因而类名是必需的。类名可以是任意合法的Java标识符,根据命名的约定,类名的每个有意义的单词的首字母要大写,其余字母小写。extends是引用超类的关键字。超类名用来表

15、明新创建的类是从哪个类继承而来的,被继承的类称为此类的超类,也称为父类,extends后面只能跟一个超类名称。implements是引用接口的关键字。接口名用来声明这个类实现了哪些接口,接口名可以有多个。关于超类和接口的区别,我们将在后面进行详细讨论。类体定义了类的具体的实现,它是用大括号括起来的一个块,如下所示:属性的声明方法的声明类体中可以有属性的声明(用来定义对象的属性),方法的声明(用来定义对象的行为)。它们都是可选的。其中属性的声明和方法的声明属于类的成员声明。类体中的这些声明没有先后顺序之分,您可以以任意的顺序声明它们。但为了类的可读性,我们建议您按照上面出现的顺序声明它们。修饰符

16、有三个,它们分别是public、abstract、final。public修饰符表示定义的这个类可以在它所在的包以外声明及使用;abstract表示定义的类是一个抽象类;final表示定义的类是一个最终类,即它不能作为其它类的超类。一个类可以有多个修饰符,但是不能有几个相同的修饰符,比如两个public是错误的。当一个类有多个修饰符时,这些修饰符无先后顺序之分,您可以任意的排列它们,但是我们建议您按照public abstract final的顺序写。例如:public abstract ClassB extends ClassA注意:abstract和final不能同时作为一个类的修饰符。因

17、为抽象类只是一个没有实现的虚类,必须再为实定义一个实类,才能被使用,其原因我们将在以后讲述。下面这一个“人”的类的例子,在生成这个类文件时,应在JAVA开发工具中,新建一个Java源文件People.java,在其中加入如下的代码:package com.mysite;public class Peopleprivate Name name;/姓名private String gender;/性别public People()/构造方法gender=”男”;name=new Name();public String getGender()/获取性别return gender;public vo

18、id setGender(String peoplegender) /设置性别gender =peoplegender;public void changeFirstname(Name n,String newfirstname)/修改姓名n.setFirstname(newfirstname);newfirstname="王五"public final void changeFirstname(String newfirstname)/修改姓名name.setFirstname(newfirstname);public static void main(String ar

19、gs)People p=new People();.setFirstname("张三");System.out.println("张三当前的名字是:"+.getFirstname();String nn="李四"p.changeFirstname(,nn);System.out.println("张三的名字改为:"+.getFirstname();System.out.println("nn的值是:"+nn);在这个类中: public class

20、 People定义了一个类名为People的类,注意在保存这个文件时,文件名应为People.java。private String gender;/性别表示在People类中定义了一个性别属性,属性变量名为gender,类型为字符型。public String getGender()/获取性别return gender;public void setName(String peoplegender)/设置性别gender =peoplegender;表示在People类中定义了两个方法,一个为获取一个人性别的方法getGender(),一个为设置一个人性别的方法setGender()。在Ja

21、va语言中,通常将一个类声明的文件称作一个编译单元。您可以在一个编译单元中声明多个类,但最多只能声明一个public的类。编译单元的文件名要和其中的声明为public的类名完全一样,连大小写都要一样,否则就会产生编译错误。如在一个编译单元中定义多个类时,这些类不能重名,否则会产生编译错误,因为当您使用重名的类时,编译器将无法弄清楚您指的是哪一个类。在以后您还会看到,不仅仅是在一个编译单元中,在一个包中也不允许有相同名称的多个类,即使它们并不是定义在一个编译单元中。如果在一个类文件中包括多个类,不带public修饰符的类称为私有类,即这些类只能在这个包(即此文件所在目录中的所有类的总称)中调用,

22、而不能被其它包调用,否则会产生编译错误。编译器在编译Java源程序的时候,会为每个类产生一个以类名为名称、以.class为后缀的字节码文件,保存的位置依包定义而定。如果一个编译单元中声明了多个类,正确编译以后就会产生多个字节码文件。这些文件的名称只与类名有关,和源程序文件名无关。例如,People.java文件中增加如下一段代码:class Nameprivate String surname;/ 姓private String firstname;/名public String getSurname()/获取姓return surname;public String getFirstname

23、()/获取名return firstname;public void setSurname(String sn)/设置姓firstname=sn;public void setFirstname(String fn)/设置名firstname=fn;编译此文件,会在com.mysite中得到两个结果文件:Pelple.className.class我们再建一个学生类文件。这个类是由People类继承而来。源程序如下:package com.mysite;public class Student extends Peoplepublic String levelname;/所在学段,如高中、初中

24、、小学private String gradename;/所在年级private String classname;/所在班级public void changeFirstname(Name n,String newfirstname)/修改姓名n.setFirstname(newfirstname);public String getFirstname()/获取学生名return name.getFirstname();这样,就定义了一个People类的子类,在后面我们会介绍一个子类会从父类中继承哪些功能。练习3-3有下面一个类定义代码:public final class Name ext

25、ends People,Nameprivate String oldname;public String getOldName()return oldname;请总结一下这个类定义中存在哪些问题。3.2.2属性的声明属性是指封装在类体中变量,是类成员的一部分。Java语言中属性的声明形式如下:属性修饰符 变量类型 变量名=初始值;变量类型可以是任意的Java数据类型,也可以是已定义过的类类型。变量名可以是任意合法的Java标识符,属性的变量名称也简称作属性名。在一个类中,属性名不能重复定义,否则会产生编译错误。如People类中gender即是一个属性名。属性修饰符有以下几种:publicpr

26、otectedprivatefinalstatictransietvolatile其中public、protected、private规定了属性的访问权限,一个属性只能从中选择一个或不选,它们分别代表的意义是:public表示该属性可以多层继承,并可直接进行读取及赋值操作;protected 表示该属性只能被本包中的其它类继承,并可直接进行读取及赋值操作;private 表示该属性不能被子类继承,也不能直接进行读取及赋值操作。如果一个属性前不加上述public、protected、private修饰符,表示这个属性只能在本包中的类中使用。final规定了属性是不能改变的,因此我们常常用这个修饰

27、符定义一些常量,如对这些属性进行赋值操作,将会出现错误。static表示这个属性是类属性,也称静态属性,Java语言是多任务和多线程的系统,一个类可能同时被多个应用调用,Java虚拟机为第一个实例化的类生成一个包括属性和方法的实例,在定义其它实例时,对于除static类型的属性和方法,系统将在每次实例化一个实例时,生成一个属性及方法的考贝,然后处理之;而对于static类型的属性(包括方法),只在第一次类实例化时进行定义,在定义该类的其它实例时,将不再定义static类型的属性和方法,而是共用第一次实例化的属性及方法,也就是说,对于static属性,相当于多个实例共用一个属性。对于static

28、方法,相当于多个实例共用一个方法,系统因此可以节省一些存贮空间,在定义常量时,也应加上这个修饰符。static属性在多任务处理及池处理等方面十分重要。如我们限制一个类最多只能同时运行十个实例,这时我们可以在这个类中增加一个静态变量,初始值为0,每实例化一次,便自动增1,如果这个变量大于10,则不能再进行实例化,以此达到限制类同时运行个数的目的。这在网站系统限制用户访问数时常常用到的方法。static属性在初始化时也是比较特殊的,一般是在定义属性时直接赋给一个初始值,这个赋值只在第一次实例化时起作用,生成其它实例时,将不再进行赋值。例如:package com.mysite;public cla

29、ss Example2_1public static int counter=0;public Example2_1() throws Exceptionif(counter>=5)throw new Exception("不能再创建实例!");counter+;System.out.println("第"+counter+"实例完成!");public static void main(String args)tryExample2_1 e1=new Example2_1();Example2_1 e2=new Example

30、2_1();Example2_1 e3=new Example2_1();Example2_1 e4=new Example2_1();Example2_1 e5=new Example2_1();Example2_1 e6=new Example2_1();catch(Exception e)System.out.println(e.toString();编译及运行结果如下:从这个例子我们可以看出,static属性所具有的特殊作用。transiet表示此属性不是对象的持续属性的一部分,volatile用于线程中,表示每次线程访问一个属性时都保证变量在线程中的考贝和主考贝相一致。valatil

31、e和transiet在一般编程中很少使用。属性的赋值与变量赋值是相同的,并且每一个属性均可在该类的方法(除main()方法)中使用。如果在父类中定义了一个属性,在它的子类中仍可定义与之同名的属性名,但在访问本类中的属性时,应在属性前加“this.”(如无重名的变量,也可不加)来明确是本类中的属性,在属性前加“super.”来明确是父类中的属性。例如:package com.mysite;public class Example2_3 extends Example2_2public String name="我是张三"public Example2_3()System.ou

32、t.println(name);System.out.println();public static void main(String args)Example2_3 e=new Example2_3();class Example2_2public String name="我是李四"编译及运行结果如下:3.2.3方法的声明方法是指封装在类体中的一段可执行代码,您可以传给方法一定数目的参数并调用它,它也是类成员的一部分。在Java语言的类定义中,方法声明的格式如下:方法修饰符 返回值类型 方法名(参数列表) throws异常列表 方法体方法名是用来调用

33、此方法的名字,它可以是Java语言中任意合法的标识符。按照命名的约定,方法名命名时应该是有意义的动词或动词短语组成,它的第一个字母一般要小写,其它有意义的单词的首字母要大写,其余字母小写。如Pelple类中的getGender()方法中,getGender即是该方法的方法名。返回值类型是指方法返回的结果的数据类型,可以是任意的Java数据类型,包括类类型。如果方法没有返回值,则用void表示。如果在一个方法中想中途返回,应使用return语句。如果是void类型,则无需返回结果,可直接用return;返回,如是其它类型,在return 后面必须有一个符合方法返回值类型要求的值,Java编译器会

34、检查您的代码中是否存在应该返回值的地方,如无返回一个值,在编译时将会报错。参数列表表示在调用一个参数时,可为其设置一些初始的参数,方法中会根据不同的参数获得不同的结果,参数列表是可选的。如果方法没有参数,就不用写参数列表,只要有一对小括号“()”就行了,比如People类中getGender()方法无参数,而setGender()方法中则有一个叫peoplegender的参数。参数的定义与变量的定义相同,但不可赋初始值,参数列表的形式如下:类型 参数名,省略号表示可以有多个参数,它们之间用逗号分开。在调用方法的时候,应该为每一个参数赋一个符合类型的值,且必须按照方法定义中的顺序排列。在Java

35、语言中,参数传递值是比较复杂的。但我们只须记住一点,凡是基本数据类型的参数,参数传递采用的是值传递方式,参数变量的值在方法中发生值变化时,不影响原实际参数;凡是引用类型的参数,参数传递采用的是传引用值的方式,参数变量的值在方法中发生变化时,会影响其实际参数,这种参数传递的方式与变量赋值是一致的。在我们编程过程中,一定要注意参数值变化是否会影响到变量值的问题,防止因此而出现的意外错误。throws子句定义了在方法执行中可能导致的异常声明。丰富的异常处理是Java语言的一大优势,这方面的详细内容请参见第二章和第四章的相关内容。方法体是一个实现了这个方法功能的代码块,也可简单的是一个分号“;”。当且

36、仅当方法的修饰符中有abstract或native时,方法体是一个分号。方法修饰符用于限定方法的访问权限和实现机制,可以是以下几种:public、protected、private、abstract、final、synchronized、native。其中public、protected、private表明了方法的访问权限,含义与属性中的含义相同。abstract说明此方法为抽象方法。抽象方法是指未定义方法体的方法,其方法体将在实方法中定义。final说明此方法为最终方法,以此方法名命名的方法不能在这个类的子类中重新定义,不管子类方法中的参数是否与其参数相匹配,这和属性中final的含义不同。

37、static说明此方法为类方法或称静态方法,其含义在介绍static属性时已有介绍。有static修饰符的方法中不能调用本类中的非静态属性或方法,否则编译时会出错,这也是是否使用static修饰符的原则,如编译不出错,应尽量使用static修饰符,以减少方法考贝浪费的空间。例如:package com.mysite;public class Example2_4 public static String name="我是张三"public String gender="男"public static String getName()return name

38、;public String getGender()return gender;在这个例子中,因name是一个静态属性,因此,可将getName()方法可设为静态方法,而getGender()方法中使用了非静态属性gender,因此,不能设定为静态方法。练习3-4:上例中如将getGender()方法设置为静态方法(增加static修饰符),结果会如何?synchronized用于在执行该方法之前给方法上锁,上锁的目的是保证该方法只能有一个调用在执行,只有调用这个方法的进程执行完毕后,其它进程才能调用。这在多任务和多进程的系统中,防止一个方法同时执行多个造成冲突的情况。native指明此方法为

39、本地方法。所谓本地方法,是指针对具体的操作(如对windows系统的操作),通过其它语言(如C+),将一些要实现的功能编译成动态执行库(DLL),然后通过一定的机制,由java语言调用。JAVA语言在实现硬件控制及要求响应速度较高的功能时,常常采用这种方法,事实上,在JDK中,也有大量方法采用了这种方式。jre中的很多动态库就是用于处理本地方法的。本地方法的实现可参见附录二。在一个类中,方法名相同的方法可以有多个,但这些方法所带的参数个数、参数数据类型及参数的顺序不能完全一样,Java语言在调用时,会根据参数情况选择合适的方法。这些方法的返回值可以相同,也可以不同。这体现出面向对象编程中的一个

40、非常重要的特性:重载。如在People类中定义了两个changeFirstname()方法:public final void changeFirstname(Name n,String newfirstname)/修改姓名n.setFirstname(newfirstname);newfirstname="王五"public final void changeFirstname(String newfirstname)/修改姓名name.setFirstname(newfirstname);类中有这两个方法是合法的,但要注意这两个方法中的参数个数不同。方法名可以和其超类的

41、方法名(包括参数)相同,如果有方法名和参数名完全一样的方法,java语言在调用时首先调用本类中的方法,这体现出对象的又一个非常重要的特性:覆盖。如Student类中的方法changeFirstname(String newfirstname)将覆盖People类同相同的方法changeFirstname(String newfirstname),但不覆盖方法名相同,而参数不同的另一方法changeFirstname(Name n,String newfirstname)。在子类中重新定义与超类中方法名和参数相同的方法时,如超类中的方法是一个类方法(即有static修饰符的方法),则子类中也只能

42、再定义类方法。但如果参数不同,则无此约束。练习3-5将Student类中public static void testMethodOverride()方法中的static去掉,编译结果如何?如在Student类中增加如下代码,编译结果又如何?publicvoid testMethodOverride(String s) /测试方法覆盖int i=11;重载与覆盖的区别:重载是方法名相同而参数(个数、顺序及类型)不同的多个方法,包括本类与超类中的方法;覆盖是指在本类中定义一个方法名和参数(包括顺序及类型)均与超类中的方法相同的方法,覆盖不能在本方法中进行,也无意义。在本类中可调用直接超类的pro

43、tected方法以及所有public方法,这体现出对象的另一个非常重要的特性:继承。如在学生类的下述方法中:public String getFirstname()/获取学生名return name.getFirstname();name属性则是继承了People类中的name属性。在方法名定义中,有几个特殊命名的方法,这些方法具有特殊的含义,它们是:构造方法。即方法名和类名完全一样(包括大小写),在为类进行实例化时调用就是这个方法。构造方法不是必须定义的,但我们常常定义一个,用于初始化一些数据。构造方法可以有多个,但所有构造方法均不得定义返回值类型。如People类的构造方法如下:publi

44、c People()/构造方法不带参数的构造方法即使不定义,Java语言的编译器会自动为这个类创建这个类。main()方法。这是直接运行Java类的默认调用的方法,其带参数为String args,即在运行java类时所带的参数。在DOS窗口执行一个类文件时,其格式如下:java 类名 参数名,参数名所带的参数名将会传递给args参数。main方法也不是必须的,但我们为了运行一些简单的任务或进行方法的测试,常常加上这个方法,在程序正式发布时,除非是直接使用main()方法进行处理,否则,建议将这个方法中的方法体注释掉。main方法必须是public static 型的,一般返回类型为void。

45、虽然main()方法是放在了类的方法里,但在main()中不能直接操作该类中的属性和方法,必须首先对这个类进行实例化后,才能使用该类的属性或方法。如在People类的main()方法中,定义了一个对象名为p的对象后,才可进行相应的操作。public static void main(String args)People p=new People();.setFirstname("张三");System.out.println("张三当前的名字是:"+.getFirstname();String nn="李四"p

46、.changeFirstname(,nn);System.out.println("张三的名字改为:"+.getFirstname();System.out.println("nn的值是:"+nn);在方法体中,可以直接调用本类及其超类中的属性与方法。如果有重载或者覆盖的方法,可通过在属性名或方法名前加“this.”表示调用本类中的属性或方法,在属性名或方法名前加“super.”方法表示调超类中的属性或方法,“super.”可重调用,如是合法的。super.方法针对所有超类中的public 属性及方

47、法适用,如果超类中的属性或方法定义为private或非直接超类中的方法或属性定义为protected类型,则不能使用“super.”来调用。在Java语言机中,如果我们需要使用一个类,Java虚拟机会首先装入这个类(详细知识以后会介绍),我们可能需要在装入一个类时就执行一段代码(如只进行一次初始化),如果把这段代码放入构造方法中,则会出现每次实例化一个对象时,就要执行一次,为此Java语言专门有实现此功能的机制,可称为“类装入初始化”,即通过定义一个static语句块来实现,其形式如下:static .如果有多个这样的语句块,这些块将按顺序执行。这些语句只在第一次装入时执行一次,以后将不再执行

48、。这些代码将先于构造方法执行,这一点是非常重要的。当然,如果你要求每次实例化就要执行一段代码,把这段代码放入构造方法中即可。例如:package com.mysite;import java.io.*;import java.util.*;public class Example2_5public static void main(String args)B b1=new B();B b2=new B();class Bpublic B()System.out.println("初始化B");static System.out.println("执行代码1&quo

49、t;);static System.out.println("执行代码2");编译及执行后,执行结果如下:3.3创建对象(类实例化)Java是一种面向对象的编程语言,使用Java编程的时候,您必然要处理大量的对象。您要创建它们,修改它们,改变它们的属性,调用它们的方法,将它们和其它对象有机地组织起来,完成一个的功能。下面我们分别介绍这些内容。创建对象当您编写Java程序的时候,您定义了一些类。正如前面所介绍的,类是对象的模板,在大多数情况下,您需要使用类创建对象,然后和这些对象打交道。字符串对象是一个特殊的类,创建时最为简单,您只需要将一个字符序列用双引号括起来即可。编译器

50、会自动的为这些字符串文字创建对象,而不需要您显式地去创建对象。您可以把这样的字符串赋给一个字符串类型的变量。例如:String s = "I am a String object."也可以用标准的方法定义字符串类,例如:String s = new String("I am a String object.");Java编译器会为字符串文字显式的创建对象,对于其它类,必须采用下面的方法定义类的实例: 类名 实例变量 = new 类的构造方法(参数列表);类名是定义要创建的实例所属的类的名字。new是一个创建实例所必须的关键字。类的构造方法是指类及其子类的

51、构造方法,因在定义构造方法是与类名或子类名一样的,原则上类名与构造方法名相同,但如果类名与构造方法名所指的类存在超类与子类的关系,Java语言就可以进行类型转换。参数列表是指类的构造方法所带的参错,当找不到与参数列表中的参数表达式类型和个数相匹配的构造方法时,会产生编译错误。3.3.2对象的引用Java语言中的引用概念在前面已经介绍过,在Java语言中,引用值是隐藏的,不能在程序中直接操作。这样的设计大大增强了Java语言的安全性,基于这一特点,我们也称java语言是健壮的。当您使用对象的时候,您实际上是通过对象的引用值来定位和使用对象的。当您将一个对象赋给一个类型匹配的变量时,您实际上是把这

52、个对象的引用值赋给了这个变量,当对一个类变量的属性进行改变时,这种改变将直接作用在该变量所对应的实例的属性,如果有几个变量同时指向该实例,则其它变量所对应的属性值也会同时变化。这和采用值传递方式的基本数据类型是有很大区别的。另外,针对字符串类型,其赋值是采用引用方式的,但其处理全部采用的是生成新字符串的方式处理的,因此,在字符串变量值的变化方式有点向基本数据类型。对象引用的方式会对程序处理有很大变化,我们应该牢记。例如:package com.mysite;import java.util.*;public class Example2_6 public void testReference(

53、int i,String s,Vector v)i+;s="新字符串"v.set(0,"新元素");public static void main(String args)Example2_6 e=new Example2_6();System.out.println("执行testReference前:");int i=5;String s="旧字符串"Vector v=new Vector();v.add("旧元素");System.out.println("i="+i+

54、"ns="+s+"nv1="+(String)v.elementAt(0);e.testReference(i,s,v);System.out.println("执行testReference后:");System.out.println("i="+i+"ns="+s+"nv1="+(String)v.elementAt(0);执行结果如下:通过对testReference()方法的几个参数的分析,可以更好的理解不同数据类型作为参数引用时的方法。其中基本数据类型(i)和字符串

55、类型(s)在执行testReference()方法后,并未影响原变量,而类类型变量(v)在调用后,原变量的内容发生了变化。3.3.3对象的类型转换在Java语言中,如果两个类在继承上存在子类或超类的关系,一个类的实例就可以转换为另一个类的实例。具体说来,如果类A是类B的子类或超类,那么类A的实例就可以转换为类B的实例。对象的类型转换有两种方式:隐式转换和显示转换。这和基本数据类型的转换是类似的。隐式转换是指在实例化一个对象时,直接调用子类的构造方法来实现。如:People p=new Student();这也符合一个常理,因为一个学生首先是一个人。注意:不能通过隐式转换将一个类的超类实例化后给

56、子类对象。显示转换是指在一个对象前直接声明一个类名的方式进行强制转换,如:Stuent s= new Student();People p=(Student)s;在Java语言中,有一个类是所有类的超类,那就是Object类,很多JDK中的类(如Vector)就是直接操作Object类的,我们可以通过显式转换的方式,将我们需要处理的对象看作是Object对象来对待。例如:package com.mysite;import java.util.*;public class Example2_7 public static void main(String args)Vector v=new Ve

57、ctor();Date d1=new Date();v.add(d1);Date d2=(Date)v.elementAt(0);System.out.println(d2);在这个例子中,Vector对象中保存的是Object对象,在v.add(d1)语句中,因编译器知道任意对象均为Object的子类,因此可直接保存,而在Date d2=(Date)v.elementAt(0);语句中,因编译器不知道Vector对象中保存的对象与Date对象之间的关系,因此必须通过显示转换才能进行赋值操作。练习3-6:如果删除上例中的“(Date)”代码,编译及运行结果会如何?下面一段代码:package com.mysite;public class Example2_8

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论