4章.docx
- 文档编号:4666073
- 上传时间:2022-12-07
- 格式:DOCX
- 页数:20
- 大小:25.74KB
4章.docx
《4章.docx》由会员分享,可在线阅读,更多相关《4章.docx(20页珍藏版)》请在冰豆网上搜索。
4章
第4章类和对象
本章主要介绍Java语言中类的定义及类的访问控制、成员的定义及成员的访问控制、对象的创建、数组的创建及使用。
第4章类和对象
4.1OO(Object-oriented)基本概念
4.2类的定义
4.3域(成员变量/字段)声明
4.4方法的定义
4.5类变量的初始化形式
4.6类对象的初始化形式
4.7数组
4.7.1数组的创建形式
4.7.2(一组)数组的应用
4.7.3多维数组
4.8对象的撤消(清除)
4.9小结
4.1OO(Object-oriented)基本概念
1.类(Class)
类是一组具有共同的属性特征和行为特征的对象的抽象。
(1)属性(Attribute)
是描述对象静态特征的一个数据项。
(2)服务(Service)
是描述对象动态特征(行为)的一个操作序列。
2.对象(Object)
对象是一组数据(属性)及对这组数据属性的一组操作(行为)构成的有标识的独立实体。
类与对象的关系:
抽象与具体的关系。
类是产生对象的模板,而对象是类的一个实例。
3.封装(encapsulation)
是指通过类机制把对象的数据和对数据的操作(行为)封装在一起成为一个独立的系统单位。
4.2类的定义
4.1.1类的定义形式
Java程序由类构成,类由类头和类体组成,其一般形式为:
[<修饰符>]class<类名>
{<每个字段的声明>
<每个方法的定义>
}//类定义结束
其中类的修饰符有2种:
(1)访问控制符
public、private或缺省来指定类的访问权限。
如:
publicclassObject{....}
(2)非访问控制符
abstract、final分别用来声明抽象类和最终类。
如:
publicfinalclassSystem{....}
下面我们定义一个平面上的点类Point,如下:
//文件名:
Point.java
publicclassPoint
{privateintx,y;//坐标
publicvoidsetPoint(inta,intb)
{x=a;y=b;}
publicvoidmove(intdx,intdy)
{x+=dx;y+=dy;}
publicintgetX(){returnx;}
publicintgetY(){returny;}
publicStringtoString()
{return“(“+x+”,”+y+”)”;}
}
4.1.2类的访问控制修饰符及访问权限
和C++不同,访问权限有二层,外层为类的访问权限,由类访问控制符来指定。
内层是成员的访问权限,由成员访问控制符指定。
类的访问控制符有:
(1)public及公有访问权限
如:
publicclassA{...}
classC
{Aobj=newA();...}
公有类可被任何程序包中的所有类引用。
引用是指在类中或者在它们的方法体内,都可以创建该类的对象、访问这个类内可见的成员变量和调用它的方法。
(2)缺省及包访问权限
如:
classB{...}//B是友类
classD
{Bobj=newB();...}
缺省时声明的类称友类,友类具有包访问权限。
友类只可被同一个程序包内的所有类引用。
一般将相关的类放到同一个程序包内,在包内它们能自由访问,对外隐藏,可实现“内外有别”的封装机制。
说明1点:
同一个编译单元(Java源文件)的类属于同一个程序包。
(3)private及私有访问权限(后续介绍)
私有类具有私有访问权限。
私有类只能被外部类访问。
因此,只有内部类才允许声明为私有类,而普通类或包含内部类的外部类是不允许声明为私有类。
classOuter
{Innerobj=newInner();//合法
privateclassInner//私有的内部类
{.....}
}
classX
{Outer.Innerobj;...}//非法
4.3域/成员变量/字段(field)
4.3.1域(field)的声明
一般来说,类体包括一个或几个域的声明。
域的声明形式:
[访问控制修饰符][修饰符]<类型><变量名表>;
其中[]中的项可以省略。
4.3.2域的访问控制符及访问权限
(1)public
公有域可被任何类访问。
即在其它类体内或者是方法体内,可以对该成员变量进行读或写。
(2)protected
保护域可被本类访问,也可被同一包内的其它类访问,还可被其它包内的该类的子类访问。
备注:
包及包的使用方法在下一章介绍。
(3)缺省
缺省域可被本类及同一包内的其它类访问。
(4)private
私有域只能被本类的所有方法访问。
它常用来描述那些需要隐藏起来的数据信息,其他类只有通过调用该类的公有方法才能访问到它们,这就是所谓的面向对象的“数据封装和信息隐藏”的基本思想。
下面定义的是时间类Time。
classTime
{privateinthour,minute,second;
publicTime(){hour=minute=second=0;}
publicTime(inth,intm,ints)
{setTime(h,m,s);}
publicvoidsetHour(inth)//设置小时
{hour=h>=0&&h<24?
h:
0;}
publicvoidsetMinute(intm)//设置分
{minute=m>=0&&m<60?
m:
0;}
publicvoidsetSecond(ints)//设置秒
{second=s>=0&&s<60?
s:
0;}
publicvoidsetTime(inth,intm,ints)
{setHour(h);setMinute(m);setSecond(s);}
publicintgetHour(){returnhour;}
publicintgetMinute(){returnminute;}publicintgetSecond(){returnsecond;}
}//Time定义结束
4.3.3成员变量(域)的类型
2种:
静态域(类变量)和非静态域(实例变量)
用static声明的域称类变量,未用static声明的域称实例变量。
注意:
不同的对象关于静态域只有一个副本,在程序加载时系统就为它分配内存了,而不同的对象关于实例变量有不同的副本,在对象创建时才生成。
下面是圆类Circle的定义:
publicclassCircle
{publicfinalstaticdoublePI=Math.PI;//类变量
privateintradius;//实例变量
publicstaticdoublegetPI(){returnPI;}
publicvoidsetRadius(intr){radius=r;}
publicintgetRadius(){returnradius;}
publicdoublegetArea()
{returnPI*radius*radius;}
}
关于成员变量说明2点:
(1)有两种访问类变量的方法:
类名.类变量名
对象名.类变量名
下面是访问实例变量的唯一方式:
对象名.实例变量名
(2)两种成员变量都可以在声明的同时赋初值。
当没有赋初值时,系统将用缺省值对其初始化,见教材P.67。
成员变量的默认初值
类型
默认初值
boolean
false
char
'\u0000'
byte、short
(byte)0、(short)0
int、long
0、0L
float、double
+0.0f、+0.0
引用型变量
null
4.3.4最终域
最终域就是指用final声明的成员变量。
最终域初始化后不能被修改。
如:
publicclassCircle
{publicstaticfinaldoublePI=Math.PI;...
//该方法体内不能有setPI()
}
用final声明域时,要注意以下2点:
(1)同时需要指出tatic。
4.3.5域的作用域
域的作用域开始于声明处,结束于类的右花括号处。
域的作用域大于形参(是自动变量)的作用域,如:
classPoint
{privateintx,y;
//……
publicvoidsetPoint(intx,inty)
{this.x=x;this.y=y;}
}
4.3.6域的数据类型
域(成员变量)的数据类型可以是两种:
基本数据类型和引用类型(类、接口、数组等)。
4.4方法的定义
一般地说,方法的定义形式为:
[<访问控制修饰符>][<修饰符>]<返回类型>
<方法名>(<形参表>)
{<语句序列>
}
4.4.1方法的访问控制符及访问权限
同成员变量,有四种:
public、protected、缺省、private。
让我们来回忆一下这四种访问权限。
4.4.2构造方法和创建对象
(1)构造方法
用于初始化类对象的实例变量。
注意构造方法常被重载。
如:
为Point类定义构造方法。
classPoint
{privateintx,y;//坐标
publicPoint(){x=0;y=0;}
publicPoint(inta,intb){x=a;y=b;}
publicPoint(Pointr){x=r.a;y=r.b;}
//....
}
说明3点:
(a)当类中没有定义任何构造函数时,编译器自动产生一个函数体为空的缺省构造函数如下。
一般来说,应该为类定义构造函数。
publicX(){}
(b)当用已存在的对象初始化正在创建的对象时,将调用拷贝构造函数,其一般形式为:
publicX(Xp){每个实例变量间的拷贝操作}
(c)与C++不同,Java不产生缺省拷贝构造函数,若程序中要用时,必须自行定义拷贝构造函数。
(2)创建对象
对象创建的一般形式:
new<构造方法名>(<实参表>)
上述表达式创建的对象是匿名的,返回值为被创建对象的引用,要访问创建的对象,必须建立对象和对象引用变量(简称引用或句柄)的连接。
形式如下:
<类名><引用变量名>=new<构造方法名>(<实参表>);
或
<类名><引用变量名表>;
……
<引用名>=new<构造方法名>(<实参表>);
阅读下面的程序并写出程序输出。
public class Test
{ public static void main(String[] args)
{ String foo=newString("blue");
//String foo="blue";
String bar=foo; foo="green";
System.out.println(bar);
}
}
说明3点:
(1)对象引用和其指向的对象是两个实体。
对象是匿名的,只能通过对象引用来访问。
(2)建立对象和其引用间的连接。
(3)对象和指向它的对象引用应属于同一种类类型,不同类型的对象引用和对象间一般无法直接建立连接的。
4.4.3静态方法(类方法)和非静态方法(实例方法)
用static声明的方法称类方法,是每个对象所共享的方法。
否则称实例方法,它是某个具体类对象(实例)的方法。
注意3点:
(1)调用类方法时,应用类名做前缀,最好不用对象名做前缀。
(2)在类方法内,不能直接访问实例成员,只能访问类成员。
classB
{intx=0;
staticpublicvoidfun()
{x=1;//非法,不能访问实例变量x
}...
}
(3)实例方法体内,既可以访问实例成员(实例变量和实例方法),也可以访问类成员。
4.4.4方法的重载
指重新定义已有的方法,得到的方法称重载方法。
对方法重载时必须遵循函数名相同,但参数表不同(个数不同或参数类型不同)。
如:
classPoint
{privateintx,y;//坐标
publicvoidsetPoint(inta,intb)重载方法1
{x=a;y=b;}
publicvoidsetPoint(Pointp)//重载方法2
{x=p.x;y=p.y;}
……
}
4.4.5this引用(变量)和实例方法
类的实例方法都有一个隐含的引用变量,称为this引用变量,简称this引用。
当1个对象调用某个实例方法时,它的this就指向那个对象。
在实例方法内访问的实例成员,都是this所指对象的实例成员;所以this引用往往省略。
如:
classPoint
{privateintx,y;//坐标
publicvoidsetPoint(Pointp)
{x=p.x;y=p.y;}//省略了this
publicvoidsetPoint(intx,inty)//重载
{this.x=x;this.y=y;}//此处的this不能省略
publicvoidmove(intdx,intdy)
{x+=dx;y+=dy;}//省略了this
publicdoublegetX(){returnx;}
publicdoublegetY(){returny;}
publicStringtoString()
{return“(“+x+”,”+y+”)”;}
}
在使用时注意3点:
(1)类方法没有this,所以在类方法体内不能访问实例变量及实例方法;
(2)当实例变量与实例方法的自动变量同名时,必须显式使用this,见上面的例子。
(3)对于重载的构造方法,可以在一个构造方法体内使用“this(参数表);”形式来调用本类另一个构造方法。
如:
classPoint
{privateintx,y;//坐标
publicPoint(){this(0,0);}
//this代表本类名,该语句必须是第一行语句
publicPoint(inta,intb){x=a;y=b;}
……
}
4.5类变量的初始化形式
有2种形式:
(1)在声明类变量的同时指定初始值,若未指定则用缺省值。
publicclassCircle
{publicfinalstaticdoublePI=3.1415926;
//省略其它成员
}
(2)在类中用static开头的语句块(静态初始化块)对类变量初始化,格式为:
static
{<语句序列>
}
如:
publicclassA
{publicstaticinta=1,b=0;
static
{a=0;b=1;
System.out.println("a="+a+"b="+b);
a=10;b=10;
}
publicstaticvoidmain(Stringargs[])
{System.out.println("a="+a+"b="+b);}
}
说明3点:
(1)静态初始化器在它所属的类加载到内存时由系统执行。
(2)一个类允许有多个静态初始化器,按它们出现的先后次序被执行。
(3)静态初始化器中的语句不能访问实例成员。
4.6类对象的初始化形式
对象的实例变量的初始化形式有3种:
(1)在声明实例变量的同时指定初始值,若未指定则用缺省值。
例如:
publicclassCircle
{publicfinalstaticdoublePI=Math.PI;
privateintradius=1;
privateintx=0,y;
publicintgetRadius(){returnradius;}
publicintsetRadius(intr){radius=r;}
...
}
指出newCircle()的执行过程。
(2)用初始化块
publicclassCircle
{publicfinalstaticdoublePI=3.1415926;
privateintradius=1;
privateintx=0,y;
{x=1;y=0;}//初始化块允许有其它的语句
...
}
指出newCircle()的执行过程。
(3)用构造方法初始化(必须定义)
publicclassCircle
{publicfinalstaticdoublePI=3.1415926;
privateintradius,x,y;
{x=1;y=1;}
publicCircle(){radius=1;x=0;y=0;}
publicCircle(intr,intx,inty)
{radius=r;this.x=x;this.y=y;}
...
}
试分析表达式:
newCircle(2,2,2)的执行过程。
4.7数组
4.7.1数组的创建形式
在Java中,数组被当成一种对象来处理,因此数组的创建也是用new操作符。
数组元素的类型可以是基本数据类型、类、接口等。
在Java中,创建数组有如下3种方式:
1.先声明数组的引用再创建数组
(1)声明数组引用
形式如下:
<元素类型>[]<数组引用>;//<数据类型><数组引用>[];
注意:
声明时不能指定数组的大小。
例如:
int[]oneDim;//intoneDim[];
oneDim[0]=0;//不能通过编译
(2)创建数组
形式:
<数组引用>=new<数组元素类型>[<元素个数>];
例如:
oneDim=newint[6];//每个元素取0值
注意:
数组创建后,系统用缺省值初始化每个数组元素。
2.声明引用的同时创建数组
<元素类型>[]<数组引用>=new<元素类型>[<元素个数>];
注意:
每个元素取缺省值。
例如:
intoneDim[]=newint[6];
StringcountryName[]=newString[3];
//创建对象数组
byte[]twoDim[]=newbyte[2][3];
3.声明、创建数组的同时初始化数组元素
如:
intoneDim[]={1,2,3,4,5,6};//省略了newint[]
String[]yellow={"blue","green","red"};//省newString[]
byte[]twoDim[]={{1,2,3},{4,5,6}};//省newbyte[][]
关于数组说明4点:
(1)所有的数组都有一个成员变量length,表示数组的长度,其值不能修改,在程序中用oneDim.length查询数组的大小。
(2)初始值可以是常量、变量或复杂表达式。
(3)对象数组的元素必须有一个确定值。
(4)若访问数组下标越界,JVM将抛出ArrayIndexOutOfBoundsException类型的异常,然后中止程序执行。
4.7.2(一组)数组的应用
一个数组经声明、创建或初始化后就可以存取它,下面介绍数组的2个重要的使用场合:
一是作为方法的形参,二是作为方法的返回值。
1.数组引用作为方法的参数
在方法调用发生时,把数组引用传递给被调用方法,在被调用的方法体内就可以读/写每个数组元素。
例如,编写一个程序,实现数组的转置。
publicclassInvertArray
{publicstaticvoidinvert(inta[])
{for(inti=0;i {inttemp=a[i];a[i]=a[a.length-1-i]; a[a.length-1-i]=temp; } } publicstaticvoidmain(Stringargs[]) {intb[]={1,3,5,7,9,11}; for(inti=0;i System.out.print(b[i]+"\t"); System.out.println(); invert(b); for(intelem: b) System.out.print(elem+"\t"); } } 说明: 数组引用作为方法的形参,在使用时和C++基本上没有区别。 2.数组引用作为方法的返回值 方法的返回值是数组引用时,调用方法应该用与方法返回值类型相同的数组引用,接收被调方法的返回结果。 见下例的求斐波那契数列的Application程序。 publicclassCalFibonacci {publicstaticlong[]reFibonacci(intm)//m≥2 {long[]fibonacci=newlong[m]; fibonacci[0]=0L; fibonacci[1]=1L; for(intn=2;n fibonacci[n]=fibonacci[n-1]+fibonacci[n-2]; returnfibonacci; } publicstaticvoidmain(String[]args) {finalintn=25;intnum=1; longfib[]=reFibonacci(n);//求前25个数列项 System.out.println(“斐波那契数列前25个项: ”); for(longe: fib) {System.out.print(e+""); if(num%9==0)System.out.println();//一行9个 num++; } } } //下面是一个完成等价功能的Applet程序 importjava.awt.Graphics; publicclassReturnArrayextendsjava.applet.Applet {publicvoidpaint(Graphicsg) {intn=25; longfib[]=reFibonacci(n);//求前25个数 paintArray(g,fib); } long[]reFibonacci(intm) {longfibonacci[]=newlong[m]; fibonacci[0]=0L; fibonacci[1]=1L; for(intn=2;n
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 4章.docx