03 第三章 面向对象的程序设计.docx
- 文档编号:10191311
- 上传时间:2023-02-09
- 格式:DOCX
- 页数:18
- 大小:118.91KB
03 第三章 面向对象的程序设计.docx
《03 第三章 面向对象的程序设计.docx》由会员分享,可在线阅读,更多相关《03 第三章 面向对象的程序设计.docx(18页珍藏版)》请在冰豆网上搜索。
03第三章面向对象的程序设计
第三章:
面向对象的程序设计
学习目标
⏹类和对象的描述
⏹类,属性,方法,构造方法定义
⏹private和public访问权限的介绍
⏹源文件的布局
⏹包的声明和导入
⏹包与目录的布局
⏹CLASSPATH环境变量的使用
⏹API文档的使用
类和对象的描述
现实社会中一切皆对象。
比如:
人,树,石头,猫,鸟,汽车,地球等等。
任何一种对象都具有静态的属性,但不一定具有动态的行为。
比如:
石头。
一般情况下,对象既有静态的属性,也有动态的行为。
对象本身的属性和行为之间可以相互影响,比如:
一个人饿了(属性),就会去吃饭(行为)。
相反,这个人吃饭(行为)后,就饱了(属性),体重(属性)也增加了。
不同的对象之间也可以相互作用。
比如:
人看到汽车开过来了,就会沿着路边走。
如果这个人站在路中间不动(他不怕死),那么汽车就会停下来。
那么怎么用Java语言来实现上述功能呢?
后面实例分析有实现。
如同建筑设计师设计建筑图(建筑的蓝图),可以用该图来盖出许许多多这种风格的房子一样。
类是对象的蓝图,是用来描述对象的,你可以用该类,来实例化许许多多个该类型的对象,类就是对象的模板。
在类中定义了一套数据元素(属性)和一套行为(方法)。
数据是用来描述具体的一个对象(静态),行为是用来描述该类型对象的共性,也就是该对象能够做什么(动态),以及完成相关对象之间的交互,从而改变对象的状态。
同样对象的状态也能够对象的行为。
属性和方法都叫做类的成员。
例如杯子装水的时候:
最大盛水量和当前盛水量。
盛水的方法要始终跟踪这两个属性。
装水时改变了当前盛水量的属性,同样当当前盛水量等于最大盛水量(水装满时),就会影响装水的行为,将不再倒水。
我们下面通过一个具体事例来说明Java中如何实现以上概念。
例1:
编写一个类,描述人吃饭,体重增加这个简单操作。
下图描述了一个“人”
这是一个UML中的类图,我们对它进行简单说明。
⏹第一行:
是类名Person,代表我们正在说明一个“人”的概念。
⏹第二行:
是属性,“-”号代表这个属性只有这个类自己可以访问,weight代表属性的名字,double表示属性的类型,这里意思是“人有一个体重的特性,体重可以是小数,别人不能直接看出人有多重,必须使用某种称量体重的方法”。
⏹第三行、第四行:
是构建器,“+”号代表public访问权限,含义是任何人可以访问到它。
构建器是外界创造出这个“概念”的实际“例子”的入口,第三行是按照“缺省”方式构建,第四行是按照特定方式构建,特定方式是指按照参数指定的属性构建
⏹第五行、第六行:
是方法,其中eat方法有参数,参数名字是temp,参数类型是double,该方法的返回类型为void,该方法含义是人可以吃一定数量的食物,吃完不需要给外界任何回馈。
第六行的方法getWeight()没有参数,返回double类型,含义是看这个人的重量。
声明类
Java中的语法和C一样,语句都是以分号结束,区分大小写。
在Java技术中采用下列方法声明类:
:
}
说明:
暂时只用"public",含义为:
可以被所有其它类访问。
或者不加public,在修饰类的访问权限的时候,只有两种:
1,就是加上public,表示所有类都可以访问。
2,就是什么也不写,表示本包访问权限,在讲到包的含义时再理解。
任何合法的标识符。
它代表所声明类的名称。
Java中的标识符是由字母,数字,下划线(_),美圆符($)组成。
其中长度不受限制,不能和java中的关键字相冲突,并且是区分大小写的。
比如:
class,void等关键字。
Java中的关键字都是由小写的字母组成的,所以在我们并不知道java中有那些关键字的情况下,在定义标识符的时候,只要不全是小写的字母,就不会和java中的关键字相冲突。
声明属性。
也就是说用变量表示事物的状态。
声明构造函数。
也叫构造方法,也叫构造器。
是用来实例化该类的实例(对象)的。
声明方法。
来说明事物能够做的事情,也就是行为。
注意:
属性,方法,构造函数在类中的顺序没有固定的约束。
一般习惯性地先声明属性,后声明方法(习惯性地把构造方法写普通方法的前面)。
所以Person这个类的初始版本应该是:
publicclassPerson{
}
声明属性
:
说明:
任何合法的标识符。
它代表所声明属性的名称。
暂时只用“public”和“private”,其中private含义为:
仅能被所属类中的方法访问,这称作封装。
可以是任何原始类型(基本类型)或其它类(引用类型)。
[=
如果没有的话初始化为默认的值。
(基本类型的初始化相应的值:
比如:
int,short,byte,long,char(Unicode码值)初始化为0,float,double初始化为0.0,boolean初始化为false,所有的引用类型都初始化为null)。
注意:
Java语言与其它语言不同,在JAVA中声明属性和初始化属性值必须一句完成。
不能分开写:
先声明,再另起一行初始化。
例如:
privateinta;
a=5;//错误
privateintb=6;//声明一个属性b,并初始化为6;
在类里面除了声明语句之外,是不能直接写其它执行语句的。
a=5是赋值语句。
如果要执行语句应放在语句块(方法块,初始化块等)里执行。
据此,我们的Person类成为如下样子:
publicclassPerson{
privatedoubleweight;
}
声明构造器
:
}
说明:
是类名,构造器的名字和类名必须一样。
可以是public,指明可以被任何其它代码访问。
Private,指明仅能被同一个类中的其它代码访问。
向构造器传递参数,可以没有参数。
传递多个参数时,参数之间用逗号分开。
每个参数由参数类型和标识符组成,这和声明属性的方式很类似,但是不能向参数赋初始值。
注意:
构造器必须没有返回类型,并且构造方法的名字和类名必须一样。
当一个类里面如果没有声明构造方法,那么虚拟机将自动给该类一个默认的构造器(不带参数的构造器)。
如果在该类里面,定义了带参数的构造方法,那么虚拟机将不再为该类提供默认的构造方法,也就是该类不能按缺省方式构建了。
我们的类此时变成:
publicclassPerson{
privatedoubleweight;
//该类的默认的构造器
publicPerson(){
}
//带参数的构造器
publicPerson(doubleinit_weight){
weight=init_weight;//实例化对象时,给weight属性赋初始值
}
}
声明成员方法
}
任何合法的标识符。
可以是public,指明可以被任何其它代码访问,private:
指明仅能被同一个类中的其它代码访问。
指明方法返回值的类型。
假如方法不返回值,应被声明为void。
向方法传递参数。
传递多个参数时,参数之间用逗号分开。
每个参数由参数类型和标识符组成。
注意:
方法必须有返回类型,返回类型为void和没有返回类型是不一样的。
除了返回类型void外,有其它返回类型的方法块里必须有return语句。
我们的类此时变成(Person.java):
publicclassPerson{
privatedoubleweight;
//该类的默认的构造器
publicPerson(){
}
//带参数的构造器
publicPerson(doubleinit_weight){
weight=init_weight;//实例化对象时,给weight属性赋初始值
}
publicvoideat(doubletemp){//吃饭的方法
weight=weight+temp;//吃多少,体重就增加多少
}
publicdoublegetWeight(){//得到人的体重属性
returnweight;//返回weight属性
}
}
private封装
在类里面声明属性的时候,一般把属性的访问权限定义成private,封装的要求。
这样只能在类里面访问该属性,在类的外面是没有访问的权限的,也就是说对于该类的实例(对象),是不能够直接访问该对象的属性的。
这样就会保护对象状态不会非法改变。
比如,人的体重是不能直接修改的,通过吃饭可以增加人的体重,如果该人很瘦,是不能直接把20斤牛肉放到该人身上,就算增加该人的体重的。
同样的道理,如果该人很胖,也不能够从该人身上割下20斤肉,而让体重下降20斤。
所以我们在以上的类中声明weight属性为private。
public公共访问
在类里面声明方法的时候,一般把该方法定义成public访问权限。
在程序运行的时候,就是通过对象和对象之间的交互来实现的。
为了保证对象都能够执行功能(方法),应该把方法的访问权限定义成public。
我们对方法getWeight()的处理就是这样。
下面是测试Person的PersonApp.java
publicclassPersonApp{
publicstaticvoidmain(String[]args){
//p1是声明的变量,类型是Person类型的,并且引用了Person类的一个对象,且使用默认的构造器构造对象
Personp1=newPerson();
//p2同p1,使用带参数的构造器
Personp2=newPerson(120);
//p1所引用的对象(简称p1对象),吃了2.5斤
p1.eat(2.5);
//p2对象吃了4.3斤
p2.eat(4.3);
//打印出p1的体重
System.out.println("p1的体重为:
"+p1.getWeight());
//打印出p2的体重
System.out.println("p2的体重为:
"+p2.getWeight());
}
}
编译和运行的过程如下图:
例2
我们知道如果文件名出现重复,那么我们要放在不同的目录中,class文件作为类的字节码载体,如果存在类名重复,那么class文件就应该放到不同的目录下,就类似文件夹的方式来管理文件。
在Java里面是通过包的结构来管理类的。
下面我们就上面例子修改下,再加个类,定义不同的包,放在不同目录下进行访问。
源文件的布局
Java技术源文件只有三部分,采用下面的布局:
[
说明:
源文件命名
源文件的名字必须与该文件中声明的公有类的名字相同。
一个源文件中可以包含多个类,但是最多只能包含一个公有类,显然,这个文件的名字应该是这个public类的名字后缀是“java”。
如果源文件中不含公有类,源文件的名字不受限制。
包的声明
多数软件系统是庞大的。
为了方便管理,通常要将类组织成包。
在包中可以存放类,也可以存放子包,从而形成具有层次结构的包。
包可以根据需要任意组织,通常,要按照类的用途、含义来组织包。
如下UML包图:
Java技术提供了包的机制,以次来组织相关的类。
声明包的句法如下:
package
你可以使用package命令指明源文件中的类属于某个特定的包。
例如:
packageshenzhen.luohu;
publicclassPerson{
//…
}
package声明必须放在源文件的最前面,或者说执行代码的第一行,或者除了注释之外的第一行。
一个源文件最多只能有一条package声明。
一条package声明对源文件中的所有类起作用。
如果你的源文件中没有package声明,你的类将在“缺省”包终,这个缺省包的位置就是当前目录。
包的导入
当你想要使用包中的类的时候,可以用import命令告诉编译器类在哪里。
import命令的语法:
import
例如:
importshenzhen.nanshan.*;
importshenzhen.futian.*;
importjava.util.List;
importjava.io.*;
当你使用import指令时,你并没有将那个包或那个包中的类拷贝到当前文件或当前包中。
你仅仅是将你在import指令中选择的类加入到你的当前名字空间。
无论你是否导入当前包,当前包都是你的名字空间的一部分。
import命令指明你要访问的类。
例如,你需要访问Writer类,你需要下面的命令:
importjava.io.Writer;
如果你需要访问一个包中的所有类,你需要下面的命令:
importjava.io.*;
但是不会导入java.io下子包的类。
默认情况下,系统将自动导入java.lang包。
importjava.lang.*;//源文件里不管有没有写上该句,该句的功能永远存在。
importjava.io.Writer;与importjava.io.*;的区别如下:
如果写类名,那么虚拟机将直接从所在包里找到该加载执行,如果写*号,编译器会CLASSPATH指定的路径,一个一个路径去找,直到找到该类为止。
javac和java命令都有-classpath参数,他们就是通知编译器或虚拟机在哪些路径中查找可能用到的类。
包与目录的布局
由于编译后的字节码文件在文件系统中存放,包结构就以目录结构的方式体现,包的名字就是目录的名字。
例如,shenzhen.luohu包中的PersonApp.class文件应该在path\shenzhen\luohu目录中。
*运行的时候进入到path目录下:
path>javashenzhen.luohu.PersonApp或者
path>javashenzhen/luohu/PersonApp
我们没有使用-CLASSPATH参数,系统是如何工作的呢?
首先,系统级别的CLASSPATH环境变量应该是个“.”,表示当前路径,在运行javac或java的时候如果没有-classpath参数就会使用环境变量中的CLASSPATH环境变量,所以系统将从当前路径开始查找类,也就是在“path”路径下,那么按照shenzhen/luohu/路径查下去,确实能找到PersonApp类,所以运行正常,在这里我们把path路径称为顶层目录。
在这种情况下不能进入到shenzhen目录下运行:
path\shenzhen>javaluohu.PersonApp或者path\shenzhen>javaluohu\PersonApp,也不能进入到上一及目录运行。
假如你把shenzhen放在daima文件夹里,你也不能进入到daima那个文件所在目录下运行:
path>javadaima\shenzhen\luohu\PersonApp或者
path>javadaima.shenzhen.luohu.PersonApp
如果想在任何目录下运行正确,必须有三个限制:
⏹CLASSPATH环境变量或-CLASSPATH参数已指向顶层目录
⏹class文件确实按包路径完整结构存放。
⏹类的名字必须是全限定名,就是必须包含包路径的类名。
上面是运行时的目录结构,我们可以通过拷贝的方式将类文件防止为以上形式并运行成功。
我们也可以在编译的时候用下面两种方式把包的结构生成出来。
通常我们需要把源文件和类文件完全分离,例如我们我们把源文件按包路径完整的存放到src目录中,我们将来编译的类文件将按照包路径完整的存放到build目录中,如下图:
为了达到以上目的,我们手工开始工作,虽然将来有集成开发环境(IDE)帮助我们,但是这对我们明白包的含义很有帮助。
1、手动建立文件夹。
把包的结构创建出来
我们分别使用三个包,在一个我们选定的工作目录下按照上图结构创建好目录,其中build目录下的结构无需创建(但是build自身要创建),src目录中存放源文件,他们分别按照自己的package声明存放到不同目录。
2、自动把包的目录结构生成出来。
进入工作目录(src和build的上级目录),执行以下命令:
就自动把类按包的结构生成到build目录中了。
其中-d指定了生成带有包结构的类的顶层目录,-sourcepath指定了源文件查找路径,显然,由于PersonApp要使用到其他包里的其他类,而这些类还是以源文件形式存在的时候,编译器必须能查找到他们并同时将他们编译成功才可以编译PersonApp自身,编译器对源文件的查找方式和虚拟机对类的查找方式类似。
//声明包
packageshenzhen.luohu;
//导入包
importshenzhen.nanshan.*;
importshenzhen.futian.*;
//公共类PersonApp
publicclassPersonApp{
publicstaticvoidmain(String[]args){
//p1是声明的变量,类型是Person类型,并且引用了Person类的一个对象
Personp1=newPerson();
//p2同p1
Personp2=newPerson(120);
//c1是声明的变量,类型是Cat类型的,并且引用了Cat类的一个对象
Catc1=newCat();
c1.jiao();
//p1所引用的对象(简称p1对象),吃了2.5斤
p1.eat(2.5);
//p2对象吃了4.3斤
p2.eat(4.3);
//打印出p1的体重
System.out.println("p1的体重为:
"+p1.getWeight());
//打印出p2的体重
System.out.println("p2的体重为:
"+p2.getWeight());
}
}
//声明包
packageshenzhen.nanshan;
//声明公共类Person
publicclassPerson{
//声明该类的一个属性,访问权限为private,对该属性进行封装,实例化时,给该属性的初始化默认值0。
privatedoubleweight;
//该类的默认的构造器
publicPerson(){
}
//带参数的构造器
publicPerson(doubleinit_weight){
//实例化对象时,给weight属性赋初始值
weight=init_weight;
}
//吃饭的方法
publicvoideat(doubletemp){
//吃多少,体重就增加多少
weight=weight+temp;
}
//得到人的体重属性
publicdoublegetWeight(){
//返回weight属性
returnweight;
}
}
//声明包
packageshenzhen.futian;
//声明公共类
publicclassCat{
publicvoidjiao(){
System.out.println("catjiao......");
}
}
运行时情况如下:
当然我们也可以在build目录下,利用CLASSPATH环境变量已经带有的.(当前路径)直接找到要运行的类(shenzhen.luohu.PersonApp),我们也可以利用绝对路径形式制定CLASSPATH,例如:
而且绝对路径相对路径的概念在编译、运行的时刻同样有效。
对于CLASSPATH我们可以通过环境变量方式设置,例如希望从系统级别设置类路径,也可以通过-CLASSPATH参数形式设置,例如希望临时更改类路径。
例3
人看到汽车开过来了,就会沿着路边走。
如果这个人站在路中间不动(他不怕死),那么汽车就会停下来
这里涉及到两个对象的相互作用,我们先声明两个类,来描述上述现象,然后再用一个测试类来实现。
〈CarPersonApp.java〉
classCar{
privatebooleanmoving;
publicbooleangetMoving(){
returnmoving;
}
publicvoidmove(booleanside){
if(side){
System.out.println("车继续行驶");
moving=true;
}else{
System.out.println("车停下来");
moving=false;
}
}
};
classPerson{
booleanside;//表示人是否在路边
publicbooleanwalk(booleancar){
if(car)//如果有车的话,人往路边走
{
System.out.println("人往路边走");
side=true;
}else{
System.out.println("人直着走");
side
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 03 第三章 面向对象的程序设计 第三 面向 对象 程序设计