Java第2版第7章Java类的特性_第1页
Java第2版第7章Java类的特性_第2页
Java第2版第7章Java类的特性_第3页
Java第2版第7章Java类的特性_第4页
Java第2版第7章Java类的特性_第5页
已阅读5页,还剩69页未读 继续免费阅读

下载本文档

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

文档简介

第7章

Java类的特性

2024/5/92通过本章的学习,主要掌握以下知识点:类的私有成员与公共成员

方法的重载

构造方法

实例成员与静态成员

this关键字2024/5/93本章的重点:

方法的重载

构造方法

本章的难点:

this关键字静态成员2024/5/947.1类的私有成员与公共成员在第6章的例子中,可以看到类的成员变量pi、radius和height可以在类Cylinder的外部任意修改。这虽然方便了程序员灵活的使用,但也存在弊端。

2024/5/95如果没有一个机制来限制对类中成员的访问,则很可能会造成错误的输入。为了防止这种情况的发生,Java提供了私有成员访问控制修饰符private。

下面来举例说明。7.1.1私有成员2024/5/96

【例7.1】在圆柱体类Cylinder中,创建类的私有成员,使之在该类的外部无法访问该成员。

//app7_1.java定义私有成员,使之无法在类外被访问classCylinder//定义Cylinder类{privatedoubleradius;//将数据成员radius声明为私有的

privateintheight;//将数据成员height声明为私有的

privatedoublepi=3.14;//将数据成员pi声明为私有的,并赋初值

doublearea(){returnpi*radius*radius;//在Cylinder类内部,故可访问私有成员

}doublevolume(){returnarea()*height;//在类内可以访问私有成员height}}2024/5/97【例7.1】续publicclassapp7_1//定义公共主类{publicstaticvoidmain(Stringargs[]){Cylindervolu;volu=newCylinder();

volu.radius=2.8;volu.height=-5;System.out.println("底圆半径="+volu.radius);System.out.println("圆柱的高="+volu.height);System.out.print("圆柱");System.out.println("底面积="+volu.area());System.out.println("圆柱体体积="+volu.volume());}}//错误!在类的外部,不能直接访问私有成员。2024/5/987.1.2公共成员如果在类的成员声明的前面加上修饰符public,则表示该成员可以被所有其他的类所访问。由于public修饰符会造成安全性和数据封装性的下降,所以一般应减少公共成员的使用。下面举例说明如何利用公共方法来访问私有成员变量。

2024/5/99

【例7.2】创建圆柱体类Cylinder的公共成员方法,来访问类内的私有成员变量

。//app7_2.java定义公共方法来访问私有成员classCylinder{privatedoubleradius;//声明私有数据成员

privateintheight;privatedoublepi=3.14;publicvoidSetCylinder(doubler,inth)//声明具有2个参数的公共方法

{//用于对私有数据进行访问

if(r>0&&h>0){radius=r;height=h;}elseSystem.out.println(“您的数据有错误!!”);}2024/5/910【例7.2】续doublearea(){returnpi*radius*radius;//在类内可以访问私有成员radius和pi}doublevolume(){returnarea()*height;//在类内可以访问私有成员height}}publicclassapp7_2//定义公共主类{publicstaticvoidmain(Stringargs[]){Cylindervolu=newCylinder();volu.SetCylinder(2.5,-5);//通过公共方法SetCylinder()访问私有数据

System.out.println("圆柱底面积="+volu.area());System.out.println("圆柱体体积="+volu.volume());}}2024/5/911程序运行结果如下:您的数据有错误!!圆柱底面积=0.0圆柱体体积=0.0【例7.2】续2024/5/9127.1.3友元若在类成员的前面加上访问控制符friendly,说明该成员是友元。友元访问控制符可以省略。也就是说在类内声明类成员时,不加任何访问控制修饰符,则该成员是一个友元。一个成员被声明为友元,表示这个成员只能被同一个包中的类所访问,但其他包中的类不能访问该成员。同理,对于类来说,如果一个类没有访问控制符,说明它具有缺省访问控制特性。这种缺省的访问控制权规定只能被同一个包中的类访问和引用,而不可以被其他包中的类所使用。

2024/5/9137.2方法的重载方法的重载是实现“多态”的一种方法。在面向对象的程序设计语言中,有一些方法的含义相同,但带有不同的参数,这些方法使用相同的名字,这就叫方法的重载(Overloading)。也就是说,重载是指相同的方法名称,如果参数个数不同,或者是参数个数相同,但类型不同,则方法就具有不同的功能。2024/5/914

注意:方法的重载中参数的类型和数量是关键,仅仅是参数的变量名不同是不行的。也就是说参数的列表必须不同,即:或者参数个数不同,或者参数类型不同,或者参数的顺序不同。同时,还要注意java中不允许参数个数或参数类型完全相同,而只有返回值类型不同的重载。方法重载的应用如【例7.3】2024/5/915classCylinder{privatedoubleradius;privateintheight;privatedoublepi=3.14;privateStringcolor;publicdoubleSetCylinder(doubler,inth){radius=r;height=h;returnr+h;}publicvoidSetCylinder(Stringstr){color=str;}publicvoidshow(){ System.out.println(“圆柱的颜色”+color);}doublearea(){returnpi*radius*radius}doublevolume(){returnarea()*height;}2024/5/916publicclassApp7_3{publicstaticvoidmain(String[]args){doubler_h;Cylindervolu=newCylinder();r_h=volu.SetCylinder(2.5,5);volu.SetCylinder("红色");System.out.println("圆柱底和高之和="+r_h);System.out.println("圆柱体体积="+volu.volume());volu.show();}}2024/5/9172024/5/9187.3构造方法前面所介绍的由Cylinder类所创建的对象,其成员变量都是在对象建立之后,再由相应的方法来赋值。如果一个对象在被创建时就完成了所有的初始化工作,将会很简洁。因此Java在类里提供了一个特殊的成员方法――构造方法。

2024/5/919构造方法(constructor)是一种特殊的方法,它是在对象被创建时初始化对象的成员的方法。构造方法的名称必须与它所在的类名完全相同。7.3.1构造方法的作用与定义2024/5/920//app7_4.java构造方法的使用classCylinder//定义类Cylinder{privatedoubleradius;privateintheight;privatedoublepi=3.14;publicCylinder(doubler,inth)//定义构造方法

{radius=r;height=h;}doublearea(){returnpi*radius*radius;}【例7.4】利用构造方法来初始化圆柱体类Cylinder的成员变量

。2024/5/921doublevolume(){returnarea()*height;}}publicclassapp7_4//定义主类{publicstaticvoidmain(Stringargs[]){Cylindervolu=newCylinder(3.5,8);//创建对象并调用构造方法

System.out.println("圆柱底积="+volu.area());System.out.println("圆柱体体积="+volu.volume());}}【例7.4】续2024/5/922程序运行结果如下:圆柱底积=38.465圆柱体体积=307.72【例7.4】续2024/5/923构造方法的特殊性主要体现在如下几个方面:1.构造方法的方法名与类名相同;2.构造方法没有返回值,也不能写void;3.构造方法的主要作用是完成对类对象的初始化工作;4.构造方法一般不能由编程人员显式地直接调用,而是用new来调用;5.在创建一个类的对象的同时,系统会自动调用该类的构造方法为新对象初始化。2024/5/924细心的读者可能会发现,在例7.4以前的例子中均没有定义构造方法,依然可以创建新的对象,并能正确的执行程序,这是因为如果省略构造方法,Java会自动调用默认的构造方法(defaultconstructor)。默认的构造方法没有参数,在其方法体中也没有任何代码,即什么也不做。如果上面例子中的Cylinder类没有定义构造方法,则系统会产生默认的构造方法如下:Cylinder(){}7.3.2默认的构造方法2024/5/925注意:只要类中定义了构造方法,系统就不在提供默认的构造方法了。如果此时要用无参数的构造方法,由于没有了自定义的一个无参构造方法,就会产生编译错误。因此,建议在定义有参数的构造方法时,同时自定义一个无参数的构造方法。2024/5/926

一般情况下,类都有一个至多个构造方法。但由于构造方法与类同名,所以当一个类有多个构造方法时,则这多个构造方法可以重载。

7.3.3构造方法的重载

构造方法重载的应用如【例7.5】

2024/5/927classCylinder{privatedoubleradius;privateintheight;privatedoublepi=3.14;Stringcolor;publicCylinder(){radius=1;height=2;color="绿色";}

publicCylinder(doubler,inth,Stringstr){radius=r;height=h;color=str;}

publicvoidSetColor(){System.out.println("该圆柱的颜色为:"+color);}2024/5/928doublearea(){returnpi*radius*radius;}

doublevolume(){returnarea()*height;}}publicclassApp7_5{publicstaticvoidmain(String[]args){Cylindervolu1=newCylinder();System.out.println("圆柱1底面积="+volu1.area());System.out.println("圆柱1体积="+volu1.volume());volu1.SetColor();Cylindervolu2=newCylinder(2.5,8,"red");System.out.println("圆柱2底面积="+volu2.area());System.out.println("圆柱2体积="+volu2.volume());volu2.SetColor();}}2024/5/9292024/5/930

从某一构造方法内调用另一构造方法,是通过关键字this来调用的。见教材例【例7.6】

。7.3.4从一个构造方法调用另一个构造方法classCylinder{privatedoubleradius;privateintheight;privatedoublepi=3.14;Stringcolor;publicCylinder(){//定义无参数的构造方法this(2.5,5,"红色");System.out.println("无参数的构造方法被调用了!");}publicCylinder(doubler,inth,Stringstr){System.out.println("有参数的构造方法被调用了!");radius=r;height=h;color=str;}

2024/5/9312024/5/932publicvoidshow(){System.out.println("圆柱底半径为:"+radius);System.out.println("圆柱体的高为:"+height);System.out.println("圆柱的颜色为:"+color);}

doublearea(){returnpi*radius*radius;}

doublevolume(){returnarea()*height;}}publicclassapp7_6{//instancevariables-replacetheexamplebelowwithyourownprivateintx;publicstaticvoidmain(String[]args){Cylindervolu=newCylinder();System.out.println("圆柱底面积="+volu.area());System.out.println("圆柱体体积="+volu.volume());volu.show();}}2024/5/9332024/5/934*this关键字总结Java关键字“this”只能用于方法体内。当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是this。因此,this只能在类中的非静态方法中使用,静态方法和静态的代码块中绝对不能出现this,并且this只和特定的对象关联,而不和类关联,同一个类的不同对象有不同的this。2024/5/935也就是说:this

变量是一个虚的变量,即对象堆中并没有分配一个内存。实际上它是对象的所有非静态方法的一个隐含参数。

比如类ClassA有一个方法MethodA(int

a),被编译系统转换后等价于访问方法MethodA(ClassA

this,int

a),这样MethodA中的this实际上是MethodA的一个参数而已,这个参数的值是一个ClassA

的实例句柄(或者说就是指针)。

这样

ClassA

a=new

ClassA();

a.MethodA(1);

转换为

ClassA

a=new

ClassA();

MethodA(a,1);

比如说下面2024/5/936如果有同一个类的两个对象,分别是a,b。你可能想知道,如何才能让这两个对象都能调用peel()方法呢:classBanana{Voidpeel(inti){………}}2024/5/937publicclassBananaPeel{publicstaticvoidmain(String[]args){Bananaa=newBanana();Bananab=newBanana();a.peel();b.peel();}}2024/5/938如果只有一个peel()方法,它如何知道是被a还是被b所调用呢?为了能简便、面向对象的语法来编写代码——即“发送消息给对象”,编译器做了一些事情,它暗自把“所操作对象的引用”作为第一个参数传递给peel()。所以上述两个方法就变成了这样:

Banana.peel(a,1);Banana.peel(b,2);2024/5/939这是内部的表示形式。我们并不能这样书写代码,并试图去调试编译;但这种方式的确是实际发生的事情。这个时侯我们采用this关键字。this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用(或者就是指代当前的对象)。this的用法和其他对象引用并无不同。但要注意,如果在方法内部调用同一个类的另一个方法,不必使用this,直接调用就可以了。2024/5/940publicclassTest6{

privateintnumber;

privateStringusername;

privateStringpassword;

privateintx=100;

publicTest6(intn){

number=n;

//这个还可以写为:this.number=n;

}

publicTest6(inti,Stringusername,Stringpassword){

//成员变量和参数同名,成员变量被屏蔽,用"this.成员变量"的方式访问成员变量.

this.username=username;

this.password=password;

}

2024/5/941//默认不带参数的构造方法

publicTest6(){

this(0,"未知","空");//通过this调用另一个构造方法

}

publicTest6(Stringname){

this(1,name,"空");//通过this调用另一个构造方法

}

publicstaticvoidmain(Stringargs[]){

Test6t1=newTest6();

Test6t2=newTest6("游客");

t1.outinfo(t1);

t2.outinfo(t2);

}2024/5/942

privatevoidoutinfo(Test6t){

System.out.println("-----------");

System.out.println(t.number);

System.out.println(t.username);

System.out.println(t.password);

f();//这个可以写为:this.f();

}2024/5/943

privatevoidf(){

//局部变量与成员变量同名,成员变量被屏蔽,用"this.成员变量"的方式访问成员变量.

intx;

x=this.x++;

System.out.println(x);

System.out.println(this.x);

}

//返回当前实例的引用

privateTest6getSelf(){

returnthis;

}

}2024/5/944

通过上面的例子我们可以理解this的用法。

第一、通过this调用另一个构造方法,用法是“this(参数列表)”,这个仅仅在类的构造方法中,别的地方不能这么用。第二、函数参数或者函数中的局部变量和成员变量同名的情况下,成员变量被屏蔽,此时要访问成员变量则需要用“this.成员变量名”的方式来引用成员变量。当然,在没有同名的情况下,可以直接用成员变量的名字,而不用this(也可以用,但是不建议使用)。第三、在方法中,需要引用该方法所属类的当前对象时候,直接用this。2024/5/945如果还不理解可以参考:Thinkinjava。2024/5/946

构造方法一般都是公有(public)的,而不可以声明为私有的,这是因为它们在创建对象时,是在类的外部被系统自动调用的。如果构造方法被声明为private,则无法在该构造方法所在的类以外的地方被调用,但在该类的内部还是可以被调用的。

见教材例7.77.3.5公共构造方法与私有构造方法2024/5/947classCylinder{privatedoubleradius;privateintheight;privatedoublepi=3.14;Stringcolor;

privateCylinder(){System.out.println("无参构造方法被调用!");}

publicCylinder(doubler,inth,Stringstr){this();radius=r;height=h;color=str;}

publicvoidshow(){System.out.println("圆柱底半径为:"+radius);System.out.println("圆柱体的高为:"+height);System.out.println("圆柱体的颜色为:"+color);}

doublearea(){returnpi*radius*radius;}

doublevolume(){returnarea()*height;}}2024/5/948publicclassApp7_7{publicstaticvoidmain(String[]args){Cylindervolu=newCylinder(2.5,5,"蓝色");System.out.println("圆柱底面积="+volu.area());System.out.println("圆柱体体积="+volu.volume());volu.show();}}2024/5/949

static称为静态修饰符,它可以修饰类中的成员。被static修饰的成员被称为静态成员,也称为类成员,否则不用static修饰的成员称为实例成员。7.4静态成员2024/5/950

在类定义中如果成员变量或成员方法没有用static来修饰,则该成员就是实例成员。对实例成员,我们并不陌生,因为在此之前编写的程序中,用到的都是实例成员。7.4.1实例成员2024/5/951用static修饰的成员变量称为“静态变量”,静态变量也称为类变量。静态变量是隶属于类的变量,而不是属于任何一个类的具体对象。

换句话说就是,静态变量不需要实例化就可以使用。当然也可以通过实例对象来访问静态变量。使用格式是:类名.静态变量名对象名.静态变量名7.4.2静态变量2024/5/952//app7_8.java静态变量的使用classCylinder//定义类Cylinder{privatestaticintnum=0;//声明num为静态变量

privatestaticdoublepi=3.14;//声明pi为静态变量,并赋初值

privatedoubleradius;privateintheight;publicCylinder(doubler,inth)//定义有2个参数的构造方法

{radius=r;height=h;num++;//当构造方法Cylinder()被调用时,num便加1}publicvoidcount()//count()方法用来显示目前创建对象的个数

{System.out.print(“创建了"+num+”个对象:”);}【例7.8】将Cylinder类里的变量pi和num声明为静态变量。2024/5/953

doublearea(){returnpi*radius*radius;}doublevolume(){returnarea()*height;}}publicclassapp7_8//主类{publicstaticvoidmain(Stringargs[]){Cylindervolu1=newCylinder(2.5,5);volu1.count();System.out.println("圆柱1的体积="+volu1.volume());Cylindervolu2=newCylinder(1.0,2);volu2.count();System.out.println("圆柱2的体积="+volu2.volume());}}【例7.8】续2024/5/954程序运行结果为:创建了1个对象:圆柱1的体积=98.125创建了2个对象:圆柱2的体积=6.28【例7.8】续2024/5/955与静态变量相似,用static修饰符修饰的方法是属于类的静态方法,又称为类方法。静态方法实质是属于整个类的方法,而不加static修饰符的方法,是属于某个具体对象的方法。7.4.3静态方法2024/5/956classCylinder{privatestaticintnum=0;privatestaticdoublepi=3.14;privatedoubleradius;privateintheight;

publicCylinder(doubler,inth){radius=r;height=h;num++;}

publicstaticvoidcount(){System.out.println("创建了"+num+"对象");}

doublearea(){returnpi*radius*radius;}

doublevolume(){returnarea()*height;}}2024/5/957publicclassApp7_9{publicintsampleMethod(inty){//putyourcodeherereturnx+y;}publicstaticvoidmain(String[]args){//在对象产生之前用Cylinder类名调用count()方法

Cylinder.count();Cylindervolu1=newCylinder(2.5,3);//用对象volu1调用count()方法

volu1.count();System.out.println("圆柱1的体积="+volu1.volume());Cylindervolu2=newCylinder(1.0,2);//用类名Cylinder直接调用count()方法

Cylinder.count();System.out.println("圆柱2的体积="+volu2.volume());}}2024/5/958注意:对于静态方法的使用,建议采用“类名.静态方法名();的形式来使用。”2024/5/959将一个方法声明为static有几个含义:(1)非static的方法是属于某个对象的方法,在这个对象创建时,对象的方法在内存中拥有属于自己专用的代码段。而static的方法是属于整个类的,他在内存中的代码段将被所有的对象所共用,而不是被任何一个对象所专用。(2)由于static方法是属于整个类的,所以它不能操纵和处理属于某个对象的成员,而只能处理属于整个类的成员,即static方法只能访问static成员变量或调用static成员方法。或者说,在静态方法中不能访问实例变量与实例方法。(3)在静态方法中不能使用this或super。因为this是代表调用该方法的对象,但现在“静态方法”既然不需要对象来调用,this也自然不应存在于“静态方法”内部。(4)调用静态方法时,可以使用类名直接调用,也可以用某一个具体的对象名来调用。2024/5/960静态初始化器是由关键字static修饰的一对花括号“{}”括起来的语句组。它的作用与类的构造方法有些相似,都是用来初始化工作的,但静态初始化器与构造方法有几点根本的不同。Static//类初始化器{ ……}7.4.4静态初始化器2024/5/9611.构造方法是对每个新创建的对象初始化,而静态初始化器是对类自身进行初始化。2.构造方法是在用new运算符创建新对象时由系统自动执行,而静态初始化器一般不能由程序来调用,它是在所属的类被加载入内存时由系统调用执行。3.用new运算符创建多少个新对象,构造方法被调用多少次,但静态初始化器则在类被加载入内存时只执行一次,与创建多少个对象无关。4.不同于构造方法,静态初始化器不是方法,因而没有方法名、返回值和参数。注:若有多个静态初始化器,则它们在类的初始化时会依次执行。2024/5/962声明一个对象的格式与声明一般变量相似,即“类名

对象名”。因而也可以将对象称之为“类类型的变量”,它属于非基本类型的变量。实际上对象是一种引用型的变量,而引用型变量实际上保存的是对象在内存中的地址(也称为对象的句柄),所以就对象的功能而言,对象是“指向对象的变量”,但就其类型而言它是属于“类类型的变量”,属于非基本类型的变量。

7.5对象的应用2024/5/963在使用对象时,一般是先用new运算符创建对象,然后再对其进行操作处理。但有时没有使用new运算符创建新对象,仍然可以对其进行赋值。7.5.1对象的赋值与比较2024/5/964classCylinder{

privatedoubleradius;privateintheight;privatestaticdoublepi=3.14;

publicCylinder(doubler,inth){radius=r;height=h;}publicvoidSetCylinder(doubler,inth){radius=r;height=h;}

doublevolume(){returnpi*radius*radius*height;}}publicclassApp7_10{publicstaticvoidmain(String[]args){Cylindervolu1,volu2;volu1=newCylinder(2.5,5);System.out.println("圆柱1的体积="+volu1.volume());//将volu1赋值给volu2,volu2也指向了volu1所指的对象

volu2=volu1;volu2.SetCylinder(1.0,2);System.out.println("圆柱2的体积="+volu2.volume());}

}2024/5/965引用变量不但可以作为参数进行传递,而且也可以作为方法的返回值。若要方法返回类类型的变量,只须在方法声明的前面加上要返回的类即可。7.5.2引用变量作为方法的返回值2024/5/966在第5章中介绍过数组

温馨提示

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

评论

0/150

提交评论