項目5 面向?qū)ο蟮某绦蛟O(shè)計基礎(chǔ)_第1頁
項目5 面向?qū)ο蟮某绦蛟O(shè)計基礎(chǔ)_第2頁
項目5 面向?qū)ο蟮某绦蛟O(shè)計基礎(chǔ)_第3頁
項目5 面向?qū)ο蟮某绦蛟O(shè)計基礎(chǔ)_第4頁
項目5 面向?qū)ο蟮某绦蛟O(shè)計基礎(chǔ)_第5頁
已閱讀5頁,還剩262頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)

文檔簡介

Java程序設(shè)計案例教程

主編魏衍君

興趣是最好的老師知識有限創(chuàng)意無限歡迎大家學(xué)習(xí)Java程序設(shè)計案例教程

項目5面向?qū)ο蟮某绦蛟O(shè)計基礎(chǔ)5.1【任務(wù)9】設(shè)計學(xué)生類Students5.2【任務(wù)10】設(shè)計本科生類和研究生類

5.3【任務(wù)11】設(shè)計抽象類Book5.1【任務(wù)9】設(shè)計學(xué)生類Students

任務(wù)描述:

編寫一個程序StudentsDemo,設(shè)計一個學(xué)生類,其屬性有姓名、年齡、學(xué)位,其方法有各種屬性的get和set方法,還要有相關(guān)數(shù)據(jù)的輸出方法,并創(chuàng)建一個學(xué)生類的對象。通過該任務(wù)的學(xué)習(xí),可以初步了解類和對象的基本概念,掌握和創(chuàng)建使用類生成對象的方法以及面向?qū)ο蟮木幊趟枷牒皖惖姆庋b特性。

設(shè)計過程:

(1)在“記事本”中輸入如下程序:

classStudents{//下面是Students類的成員變量和方法

publicStringname;

publicintage;

publicStringdegree;

publicStudents(Stringname1,intage1,Stringdegree1)//構(gòu)造方法用于初始化類

{name=name1;age=age1;degree=degree1;this.getName();this.getAge();this.getDegree();}publicvoidsetName(Stringn){name=n;}//設(shè)置學(xué)生姓名publicvoidsetAge(inta){age=a;}//設(shè)置學(xué)生年齡

publicvoidsetDegree(Stringd){degree=d;}//設(shè)置學(xué)生的學(xué)位

publicStringgetName(){returnname;}//獲取學(xué)生姓名

publicintgetAge(){returnage;}//獲取學(xué)生成績

publicStringgetDegree(){returndegree;}//獲取學(xué)生學(xué)位publicvoidshow(){System.out.println("學(xué)生的姓名是:"+name);System.out.println("學(xué)生的年齡是:"+age);System.out.println("學(xué)生的學(xué)位是:"+degree+"\\n");}}publicclassStudentsDemo{publicstaticvoidmain(Stringargs[]){Studentss1=newStudents("張三",20,"大專");System.out.println("修改前張三個人信息:");s1.show();s1.setAge(28);s1.setDegree("博士");System.out.println("修改后張三個人信息:");s1.show();}}

(2)將文件保存在“D:\\myprogram”文件夾中,文件名為StudentsDemo.java。

(3)在“命令提示符”窗口內(nèi)的“D:\\myprogram”提示符下,輸入“javacStudentsDemo.java”命令,然后在新的命令行中,輸入“javaStudentsDemo”命令,運行字節(jié)碼程序,輸出程序的運行結(jié)果,如圖5-1-1所示。圖5-1-1

程序StudentsDemo的運行結(jié)果

相關(guān)知識

5.1.1類

類是對一個或幾個相似對象的描述,它把不同對象具有的共性抽象出來,定義為某類對象共有的變量和方法,從而使程序員實現(xiàn)代碼的復(fù)用,所以說,類是同一類對象的原型。創(chuàng)建一個類,相當(dāng)于構(gòu)造一個新的數(shù)據(jù)類型,而實例化一個類就得到一個對象。Java為我們提供了大量的類庫,如果從已知類庫入手來構(gòu)造自己的程序,不僅能有效地簡化程序設(shè)計,而且能很好地學(xué)習(xí)面向?qū)ο蟪绦蛟O(shè)計方法。

類的聲明

類聲明包括關(guān)鍵字class﹑類名及類的屬性。類名必須是合法的標(biāo)識符,類的屬性為一些可選的關(guān)鍵字。其聲明格式如下:

[public|private|friendly|protected][abstract]

[final]classclassName[extendssuperclassName][implementsinterfaceNameList]

{…}

其中,第一項屬于訪問控制字符,它不僅針對于類,類的變量、方法的訪問也有該項的限制,我們后面作專門的介紹。其他的修飾符說明如下:

abstract:聲明該類不能被實例化。

final:聲明該類不能被繼承,即沒有子類。

classclassName:關(guān)鍵字class告訴編譯器表示類的聲明以及類名是className。

extendssuperclassName:extends語句擴展superclassName為該類的父類。

implementsinterfaceNameList:聲明類可實現(xiàn)一個或多個接口,可以使用關(guān)鍵字implements并且在其后面給出由類實現(xiàn)的多個接口名字列表,各接口之間以逗號分隔。

類的實體

實體是類的主要部分,包括變量的說明及該類所支持的方法,我們習(xí)慣稱之為成員變量和成員方法。需要注意的是,除了實體中定義的變量與方法外,該類還繼承了其父類的變量與方法。當(dāng)然,對父類變量和方法的訪問要受到訪問控制條件的限制。實體說明的格式為:

classclassName{

variableDeclaration

methodDeclaration

}

1.變量

Java中變量的說明可以分為兩種:類成員變量的說明和方法變量的說明。其變量聲明格式為:

[public|protected|private][static][final]typevariableName

上述聲明格式中,第一項指的是訪問控制格式(后面介紹),另外的幾項說明如下:

static:成員控制修飾符,說明該類型的變量為靜態(tài)變量,或者稱之為類變量。說明靜態(tài)變量類型后,則該類的所有實例對象都可以對其共享,而且訪問靜態(tài)變量無須事先初始化它所在的類。

final:常量聲明修飾符,與C/類似,用該符號聲明后,在程序的運行過程中不能再改變它的值。實際使用中,final往往與static結(jié)合在一起使用。比如:

finalintINDEX=1000;

staticfinalintLOOP=10;

總之,從變量定義的不同位置及所使用的限定詞來看,變量可以分為三類:實例變量、局部變量和靜態(tài)變量。

(1)實例變量。如果在類的方法代碼段之外聲明且沒有限定詞static,則為實例變量。從它的定義我們可以看出,實例變量與類緊密相關(guān),如果一個類有多個實例對象,那么每個實例對象都有自己的實例變量,之間并不影響。

(2)局部變量。如果在類的方法體之中聲明,則為局部變量,這有點與C語言函數(shù)中定義的局部變量相似。由于局部變量是在方法體內(nèi)所定義,因而只能在本方法中使用,無所謂訪問控制,也不能用static修飾符加以說明。另外,需要注意的是,局部變量使用前必須初始化,這也是它與實例變量及后面要介紹的靜態(tài)變量之間的不同之處。局部變量可以與實例變量同名而相互不影響。

(3)靜態(tài)變量。如果將一個實例變量聲明為static,則為靜態(tài)變量,或稱之為類變量。靜態(tài)變量在類聲明后就可以直接引用,但實例變量則不能,必須在實例化對象后才可以使用。

下面我們對實例變量與類變量加以詳細(xì)說明,以加深讀者的理解。比如可以如下來聲明一個成員變量:

classMyClass{

publicfloatvariable1;

publicstaticintvariable2;

}

該例中聲明了一個實例變量variable1和一個類變量variable2。今后當(dāng)創(chuàng)建類的實例的時候,系統(tǒng)就會為該實例創(chuàng)建一個類實例的副本,但系統(tǒng)為每個類分配類變量僅僅只有一次,而不管類創(chuàng)建的實例有多少。當(dāng)?shù)谝淮握{(diào)用類的時候,系統(tǒng)為類變量分配內(nèi)存。所有的實例共享了類的類變量的相同副本。在程序中可通過一個實例或者類本身來訪問類變量。例如:

MyClassA=newMyClass();

MyClassB=newMyClass();

A.variable1=100;

A.variable2=200;

B.variable1=300;

B.varable2=400;System.out.println("A.variable1="+A.variable1);System.out.println("A.variable2="+A.variable2);System.out.println("B.variable1="+B.variable1);System.out.println("B.variable2="+B.variable2);

當(dāng)從類實例化新對象的時候,就得到了類實例變量的一個副本。這些副本跟新對象是聯(lián)系在一起的。因此每實例化一個新MyClass對象的時候,就得到了一個和MyClass對象有聯(lián)系的variable1的新副本。當(dāng)一個成員變量用關(guān)鍵字static指定為類變量之后,其第一次調(diào)用的時候,系統(tǒng)就會為它創(chuàng)建一個副本,之后,類的所有實例均共享了該類變量的相同副本。所以上述程序段的輸出結(jié)果為:

A.variable1=100

A.variable2=400

B.variable1=300

B.variable2=400

2.方法

Java程序通過方法完成對類和對象屬性的操作。方法定義了在類成員變量上的一系列操作,它只能在類的內(nèi)部聲明并加以實現(xiàn),其他的對象通過調(diào)用對象的方法得到該對象的服務(wù)。方法的定義包含了兩部分內(nèi)容:方法聲明和方法體。

(1)方法聲明。方法聲明的一般格式如下:

[public|protected|private][static][final]

[abstract]

returnTypemethodName([paramList])[throwsexceptionList]

{…}

在方法聲明中應(yīng)包括方法名、方法的返回值類型、方法的修飾詞、參數(shù)的數(shù)目和類型及方法可能產(chǎn)生的例外。從其聲明格式中可以發(fā)現(xiàn),不一定要全部顯示并指明所有的信息,方法最基本的聲明格式為:

returnTypemethodName()

{…}

一般聲明格式中的第一項是訪問控制屬性,后面會有介紹。對其他幾個修飾詞說明如下:

static:說明該方法為靜態(tài)方法。與變量的定義類似,靜態(tài)方法也稱作類方法,與之對應(yīng),其他的方法就稱之為實例方法。靜態(tài)方法屬于類,所以只要對類作了聲明,就可以調(diào)用該類的類方法,即使用時無須類的初始化。當(dāng)然,實例方法只能在類的實例或子類的實例中調(diào)用。類方法只能操作類變量而不能訪問定義在類中的實例變量,這是實際使用過程中經(jīng)常出錯的地方。例如:classA{intx;staticpublicintx(){returnx;}staticpublicvoidsetX(intnewX){x=newX();}}

…AmyX=newA();AanotherX=newA();myX.setX(1);anotherX.x=2;System.out.println("myX.x="+myX.x());System.out.println("anotherX.x="+anotherX.x());…

當(dāng)編譯的時候,編譯器會給出以下的錯誤信息:

A.Java:4:Can’tmakeastaticreferncetononstaticvariablexinclassA.returnx;^

出現(xiàn)這個錯誤的原因是類方法不能訪問實例變量。

實例成員和類成員之間不同點是類成員可以在類本身中訪問,而不必實例化一個類來訪問類成員。

下面再對上面的代碼進行修改:

A.setX(1);System.out.println(″A.x=″+A.x());…

這里我們不用實例化類對象myX和anotherX就可以直接從類A中設(shè)置x并輸出。這樣同樣可以得到類變量x的值。

abstract:說明一個方法是抽象方法,即該方法只有方法說明而沒有方法體。抽象方法的實現(xiàn)須由該方法所在類的子類來實現(xiàn)。如果一個類包含一個或多個抽象方法,則該類必須為抽象類。抽象類不能被實例化。例如:classShape{abstractvoiddraw();}

該例中的說明方法draw()為抽象方法。

final:final方法類似于常量的定義,它說明了一個方法為終極方法,即它不能被子類重載。說明為final的方法往往與關(guān)鍵字private一起使用,避免出錯。例如:

privatefinalmeth_final()

{…}Java

針對任何一個方法,返回類型是必需的,如果方法沒有返回值,則返回類型為void。否則返回類型可以是各種數(shù)據(jù)類型,如int、float、String等。對于有返回值的方法,其方法體中至少有一條return語句,形式為:

return(表達式)

當(dāng)調(diào)用該方法時,方法的返回值即為此表達式的值。

(2)方法重載。Java中方法的重載指的是多個方法共用一個名字(這樣可實現(xiàn)對象的多態(tài)),同時,不同的方法要么參數(shù)個數(shù)不相同,要么參數(shù)類型不同。Java提供的標(biāo)準(zhǔn)類中包含了許多構(gòu)造函數(shù),并且每個構(gòu)造函數(shù)允許調(diào)用者為新對象的不同實例變量提供不同的初始數(shù)值。比如,Java.awt.Rectangle就有三個構(gòu)造函數(shù):

Rectangle(){};

Rectangle(intwidth,intheight){};

Rectangle(intx,inty,intwidth,intheight){};

當(dāng)傳遞不同的參數(shù)時,構(gòu)造出來的對象的實例具有不同的屬性。

(3)參數(shù)傳遞。在調(diào)用一個帶有形式參數(shù)的方法時,必須為方法提供實際參數(shù),完成實際參數(shù)與形式參數(shù)的結(jié)合,稱為參數(shù)傳遞,然后用實際參數(shù)執(zhí)行所調(diào)用的方法體。在Java中參數(shù)的傳遞是以傳值的方式進行,即將實際參數(shù)的值傳遞給形式參數(shù),而不是將實際參數(shù)的地址傳遞給形式參數(shù)。由于被調(diào)用方法沒有訪問實際參數(shù),因而在改變形式參數(shù)值時,并沒有改變實際參數(shù)的值?!纠?-1】參數(shù)傳遞舉例。publicclassExa1{staticvoidsum(Stringx,Stringy){Stringtemp;System.out.println(″形參改變之前″);System.out.println(″x=″+x+″″+″y=″+y);temp=x;x=y;y=temp;System.out.println(″形參改變之后″);System.out.println(″x=″+x+″″+″y=″+y);}publicstaticvoidmain(Stringargs[]){Stringa=″10″,b=″20″;System.out.println(″方法調(diào)用之前″);System.out.println(″a=″+a+″″+″b=″+b);Sum(″10″,″20″);System.out.println(″方法調(diào)用之后″);System.out.println(″a=″+a+″″+″b=″+b);}}運行結(jié)果:方法調(diào)用之前a=10b=20形參改變之前x=10y=20形參改變之后x=20y=10方法調(diào)用之后a=10b=20

【程序解析】

通過程序的運行結(jié)果可以看出:實際參數(shù)即a、b的值不受形式參數(shù)x、y的值的影響,即使形式參數(shù)的值改變了,實際參數(shù)的值也不會改變。

(4)構(gòu)造方法。構(gòu)造方法用來初始化新創(chuàng)建的對象。類可以包含一個或者多個構(gòu)造方法,不同的構(gòu)造方法根據(jù)參數(shù)的不同來決定要初始化的新對象的狀態(tài)。所有的Java類都有構(gòu)造方法,它用來對新的對象進行初始化。構(gòu)造方法與類的名字是相同的。比如Stack類的構(gòu)造方法的名字為Stack,而Rectangle類的構(gòu)造方法的名字為Rectangle,Thread類的構(gòu)造方法的名字為Thread。下面給出Stack類的構(gòu)造方法:

publicStack(){items=newVector(10);}

Java支持對構(gòu)造方法的重載,這樣一個類就可以有多個構(gòu)造方法,所有的構(gòu)造方法的名字是相同的,只是所帶參數(shù)的個數(shù)和類型相異而已。下面是類Stack的另一個構(gòu)造方法,這個構(gòu)造方法根據(jù)它的參數(shù)來初始化對象的大小。publicStack(intinitialSize){items=newVector(initialSize);}

從上面可以看出,兩個構(gòu)造方法都有相同的名字,但是它們有不同的參數(shù)列表。編譯器會根據(jù)參數(shù)列表的數(shù)目以及類型來區(qū)分這些構(gòu)造方法。所以,當(dāng)創(chuàng)建對象的時候,要根據(jù)它的參數(shù)是否與初始化的新對象相匹配來選擇構(gòu)造方法。根據(jù)傳遞給構(gòu)造方法參數(shù)的數(shù)目和類型,編譯器可以決定要使用哪個構(gòu)造方法。如對于下面的代碼,編譯器就可以知道應(yīng)該使用單一的整型參數(shù)來初始化對象:

newStack(10);

與此相同,當(dāng)給出下面代碼的時候,編譯器選擇沒有參數(shù)的構(gòu)造方法或者缺省的構(gòu)造方法進行初始化:

newStack();

另外,如果生成的類不為它提供構(gòu)造方法,系統(tǒng)會自動提供缺省的構(gòu)造方法。這個缺省的構(gòu)造方法不會完成任何事情。下例給出類AnimationThread的構(gòu)造方法,在其初始化過程中設(shè)置了一些缺省的數(shù)值,比如幀速度、圖片的數(shù)目等。classAnimationThreadextendsThread{intframesPerSecond;intnumImages;Image[]images;AnimationThread(intfps,intnum){super("AnimationThread");this.framesPerSecond=fps;this.numImages=num;this.images=newImage[numImages];for(inti=0;i<=numImages;i++){…}

}…}

從該例來看,構(gòu)造方法的實體跟一般方法的實體是相似的,均包含局部變量聲明、循環(huán)以及其他的語句。該例的構(gòu)造方法中出現(xiàn)了以下一條語句:

super(″AnimationThread″);

與關(guān)鍵字this相似(this表示當(dāng)前對象),關(guān)鍵字super表示當(dāng)前對象的父對象,所以使用super可以引用父類被隱藏的變量和方法。本例中調(diào)用了父類Thread的構(gòu)造方法。使用中須注意的是,父類的構(gòu)造方法必須是子類構(gòu)造方法的第一條語句,因為對象必須首先執(zhí)行高層次的初始化。構(gòu)造方法說明中只能帶訪問控制修飾符,即只能使用public、protected及private中的任一個。

(5)變量和方法的訪問控制。前面多次提到過對類、變量及方法的訪問控制屬性,比如有private、friendly、protected及public。Java中最低級的訪問控制范圍是類的級別,分為四種:同一個類、同一個包、不同包的子類及不同包的非子類。

類的訪問控制權(quán)限只能為public和friendly,變量和方法的訪問控制可以為上面四種中的任何一種。關(guān)于訪問控制權(quán)限修飾符的作用,在5.1.3節(jié)進行詳細(xì)介紹。

5.1.2對象

本項目開始的時候就討論過類與對象的關(guān)系,大家知道,類是一個抽象的概念,而對象是實實在在存在的東西,是一個具體的概念,所以對象的使用就是某個類的實例化操作。與此對應(yīng),本節(jié)分兩部分來介紹對象:對象的創(chuàng)建及對象的使用。

對象的創(chuàng)建

Java中創(chuàng)建新的對象必須使用new語句,其一般格式為:

classNameobjectName=new

className(parameterList);

此表達式隱含了三個部分,即:對象說明、實例化和初始化。

對象說明:上面的聲明格式中,classNameobjectName是對象的說明;className是某個類名,用來說明對象所屬的類;objectName為對象名。例如:

IntegeriVariable;

該語句說明iVariable為Integer類型。

實例化:new是Java實例化對象的運算符。使用命令new可以創(chuàng)建新的對象并且為對象分配內(nèi)存空間。一旦初始化,所有的實例變量也將被初始化,即算術(shù)類型初始化為0,布爾邏輯型初始化為false,復(fù)合類型初始化為null。例如:

IntegeriVariable=newInteger(100);

此句實現(xiàn)將Integer類型的對象iVariable初始值設(shè)為100的功能。

初始化:new運算符后緊跟著一個構(gòu)造方法的調(diào)用。前面介紹過,Java中的構(gòu)造方法可以重構(gòu),因而通過給出不同的參數(shù)類型或個數(shù)就可以進行不同初始化工作。如例5-2,類Rectangle定義了一個矩形類,它有多個不同的構(gòu)造方法,可以通過調(diào)用不同的構(gòu)造方法來進行初始化。【例5-2】對象的初始化舉例。importjava.util.*;importjavax.swing.*;importjava.awt.*;publicclassRectangle{publicintwidth=0;publicintheight=0;publicPointorigin;

publicstaticvoidmain(Stringargs[]){

Pointp=newPoint(20,20);

Rectangler1=newRectangle();

Rectangler2=newRectangle(p,80,40);

System.out.println("TheareaofRectangleis:"+r1.area());

System.out.println("TheareaofRectangleis:"+r2.area());

}publicRectangle(){origin=newPoint(0,0);}publicRectangle(Pointp){origin=p;}publicRectangle(intw,inth){this(newPoint(0,0),w,h);}publicRectangle(Pointp,intw,inth){origin=p;width=w;height=h;}publicvoidmove(intx,inty){origin.x=x;origin.y=y;}publicintarea(){returnwidth*height;}}classPoint{publicintx=0;publicinty=0;publicPoint(intx,inty){this.x=x;this.y=y;}}

該例中,我們定義了兩個類Rectangle、Point,并調(diào)用了類Rectangle中的area()方法來求矩形的面積。方法Rectangle()不帶參數(shù),因而只是初始化原點坐標(biāo)為(0,0),矩形的長、寬均為0;方法Rectangle(p,80,40)不僅初始化原點由類型Point()指定,同時還限定矩形的長、寬分別為80,40。

對象的使用

前面花了很大的篇幅介紹類,其目的就是為了掌握如何使用它。類是通過實例化為對象來使用的,而對象的使用是通過引用對象變量或調(diào)用對象的方法來實現(xiàn)的。與相類似,對象變量和方法是通過運算符“.”來實現(xiàn)的。1.變量的引用對象變量引用的一般格式為objectName.variableName;例如:classexample{intx;}examplea=newexample();a.x=100;

變量的引用在Java中還有一種很特殊的情況,即可以使用表達式指定變量所在的對象,例如:

intz=newexample().x;

這個語句創(chuàng)建了一個新的example對象,并且得到了它的成員變量x。需要注意的是,在這條語句被執(zhí)行后,程序不再保留對象expmple的引用。這樣,對象example就被取消引用,因而通過上述語句并不能達到初始化對象的目的。

2.對象方法的引用

與對象變量一樣,對象方法的引用的一般格式為:

objectName.methodName([argumentList]);

例如在例5-2中調(diào)用對象Rectangle中的area()方法計算矩形的面積:System.out.println(“TheareaofRectangle1is:”+r1.area());System.out.println(“TheareaofRectangle1is:”+r2.area());

雖然通過直接引用對象變量可以改變對象的屬性,但是它沒有任何意義(比如,在例5-2中,使用Rectangle類的構(gòu)造方法,可以創(chuàng)建不同的矩形,如果設(shè)置其高為height、寬width是負(fù)值,程序并不認(rèn)為其非法)。所以,較好的做法是:不直接對變量進行操作,而由類提供一些方法,對變量的引用可以通過這些方法來進行,以確保給定變量的數(shù)值是有意義的。這樣一來,Rectangle類將提供setWidth、setHeight、getWidth以及getHeight方法來設(shè)置或者獲得寬度和高度。設(shè)置變量的方法將在調(diào)用者試圖將width和height設(shè)置為負(fù)數(shù)的時候給出一個錯誤提示。這樣能夠更好地體現(xiàn)數(shù)據(jù)的封裝和隱蔽。例如,加上上述的幾個方法后,例5-2變?yōu)閜ublicclassRectangle{……publicvoidsetWidth(intwidth){if(width<0)System.out.println(″illegalnumber!″);elsethis.width=width;}publicvoidsetHeight(intheight){……}publicintgetWidth(){returnwidth;}publicintgetHeight(){returnheight;}publicvoidmove(intx,inty){origin.x=x;origin.y=y;}publicintarea(){

returnwidth*height;

}}

5.1.3類的封裝

Java是一個面向?qū)ο蟮某绦蛟O(shè)計語言,面向?qū)ο缶幊痰幕締卧穷?。我們說類是對對象的一個抽象,同時類也為對象進行了封裝。所謂封裝也就是說類的設(shè)計者只是為使用者提供類對象可以訪問的部分(包含類的成員變量和方法),而對于類中其他成員變量和方法隱藏起來,用戶不能訪問。這種數(shù)據(jù)隱藏機制和封裝機制為程序的編制和系統(tǒng)的維護提供了方便,我們不必知道程序?qū)崿F(xiàn)的細(xì)節(jié),而只要知道類可以訪問的部分,排除錯誤更為方便。

所謂封裝,指以下幾個方面:

(1)在類的定義中設(shè)置對對象中的成員變量和方法進行訪問的權(quán)限。

(2)提供一個統(tǒng)一供其他類引用的方法。

(3)其他對象不能直接修改本對象所擁有的屬性和方法。

隱藏和封裝機制是面向?qū)ο蟪绦蛟O(shè)計的特性,那么如何進行數(shù)據(jù)的隱藏和封裝呢?Java為對象變量提供4種訪問權(quán)限:public、protected、private和friendly。

對象的可見性和作用域

對于類而言,它有成員變量和方法。對于類中的成員變量,它是屬于整個類的,在創(chuàng)建對象時,自動在內(nèi)存區(qū)域分配一塊空間作為對象的屬性出現(xiàn)。同樣,類的方法中也有變量,這些變量的運行范圍只是在方法體內(nèi),如果出了方法體,那么這些變量就不起作用。

屬于類中的成員變量或方法是否就可以被其他類訪問呢?前面給出的例子中為類、方法和成員變量的定義中常常要用到“public”這個關(guān)鍵字,它的意思是允許其他類對其所定義的類、方法和成員變量進行訪問,如果不想讓其他類對其進行訪問,或者是只允許類中的方法來訪問當(dāng)前類的成員變量和方法,那么就可使用private來定義。

這里就涉及方法和成員變量的生存期問題,也就是說這些變量在程序中的哪些區(qū)域有定義。

【例5-3】引用私有方法和修改私有成員變量。

classdef{

privateintx,y,z=0;//定義私有變量

privatevoidmethod1(){//定義私有方法

intx=3,y=4,z;

z=x*y;

System.out.println(″z=″+z);

}publicvoidshow(){System.out.println(″z=″+z);

}}publicclassChange1{publicstaticvoidmain(Stringargs[]){defss=newdef();ss.method1();//直接引用私有方法出現(xiàn)錯誤ss.z=12;//直接修改私有變量是不允許的ss.show();}}程序編譯結(jié)果:>JavacChange1.javaChange1.java:15:method1()hasprivateaccessindefss.method1();//直接調(diào)用私有方法出現(xiàn)錯誤^Chnage1.java:16:zhasprivateaccessindefss.z=12;//直接修改私有變量是不允許的^

2個錯誤

【程序解析】程序要直接修改私有變量是不允許的,只有類本身和方法可以對私有變量進行訪問,這也就是我們常說的,數(shù)據(jù)封裝后,類外的方法是不能訪問私有變量的,達到數(shù)據(jù)安全的目的。

【例5-4】修改例5-3,使其能夠引用方法并修改成員變量。

classdef{

privateintx,y,z=0;

publicvoidmethod1(){

intx=3,y=4,z;

z=x*y;

System.out.println(″z=″+z);

}publicvoidshow(){System.out.println(″z=″+z);}}publicclassChange2{publicstaticvoidmain(Stringargs[]){intz=20;defss=newdef();ss.method1();//引用ss對象的method1()方法ss.show();}}程序運行結(jié)果:z=12z=0

【程序解析】程序中將method1()方法的訪問權(quán)限由private改為public,然后引用method1()方法,通過method1()方法對def類中的私有成員變量z進行訪問。

通過這個例子可以看出,對于類中的成員變量和方法,如果允許其他類對其進行訪問,可以將其訪問權(quán)限設(shè)置為public;如果要防止其他類對其進行訪問,可以盡量設(shè)置為private。

下面分別講述訪問權(quán)限修飾符的作用。

public

public顧名思義是公開的、公眾的,也就是說如果一個類被修飾為public,那么這個類就是公共類。公共類不但可供它所在包中的其他類使用,也可供其他包中的類使用,在程序中可以用import語句引入其他包中的public類。那些被public定義的類中成員變量或方法可以供其他類進行訪問,這些類、方法和成員變量可以用來供其他類訪問。

在Java中,一個程序文件只能定義一個public類,其他類可以是沒有修飾的類。

【例5-5】使用import引入已經(jīng)定義的、屬性為public的Account類,引用其方法。

publicclassAccount{//定義公共類Account

Stringname;

Stringaddress;

publicdoublebalance;//定義該成員變量是公共的

publicvoiddisplay(){//定義公共方法display

System.out.println(″name:″);System.out.print(name);System.out.println(″Address:″);System.out.print(address);System.out.println(″balance:″);System.out.print(balance);}}

定義了公共類Account以及公共成員變量balance和方法display(),將此文件保存為Account.java。

引入Account類并引用Account類定義的方法

importAccount;//引入公共類Account

publicclassUseraccount{

publicstaticvoidmain(Stringargs[]){

Accountmyaccount=newAccount();//成績類對象myaccount

=″張三″;

myaccount.address=″鄭州市黃河路19號″;

myaccount.balance=123.40;//引用myaccount對象的balance成員變量

myaccount.display();//引用display()方法,顯示輸入內(nèi)容

}

}

程序運行結(jié)果:

name:張三

address:鄭州市黃河路19號

balance:123.4

private

如果不想讓其他類進行訪問,采取什么方法呢?就是對其設(shè)置private訪問權(quán)限。

【例5-6】定義Scope類的私有方法,使用類外的方法來引用此私有方法,查看程序運行情況。

classScope{

privateintx=10;

Scope(){

intx=1000;

}privatevoida(){//設(shè)置為私有方法

intx=200;

x*=4;

System.out.println(″Aofamethodis″+x);}privatevoidb(){//設(shè)置為私有方法

x*=2;

System.out.println(″Bofamethodis″+x);}}publicclassSamp2{

publicstaticvoidmain(Stringargs[]){

intx=100;

System.out.println(″xofmainmethodis″+x);Scopeb1=newScope();b1.a();b1.b();System.out.println(″xofmainmethodis″+x);}}程序編譯結(jié)果:>javacSamp2.java

Samp2.java:22:a()hasprivateaccessinScope

b1.a();

^

Samp2.java:23:b()hasprivateaccessinScope

b1.b();

^

2個錯誤

【程序解析】在這里對Scope類的a()方法和b()方法設(shè)置為私有屬性,所以不能對其方法進行訪問,而如果要訪問,只能通過類本身所定義的方法。

例如修改Scope類中定義的構(gòu)造方法,在構(gòu)造方法中引用方法a()和方法b(),修改程序如下:

classScope{

privateintx=10;

Scope(){

intx=1000;

a();//調(diào)用a()方法

b();//調(diào)用b()方法}privatevoida(){//設(shè)置為私有方法

intx=200;

x*=4;

System.out.println(″Aofamethodis″+x);}

privatevoidb(){//設(shè)置為私有方法

x*=2;

System.out.println(″Bofamethodis″+x);

}

}

【程序解析】當(dāng)創(chuàng)建對象時,系統(tǒng)自動引用構(gòu)造方法,而在構(gòu)造方法中添加調(diào)用a()和b()方法,這樣就可以使用類中的方法來訪問類中的私有成員變量和方法。

protected

使用protected定義的成員變量或方法具有二重性,類本身、子類或包中的方法可以訪問它們,而對于其他類沒有訪問權(quán)限。

【例5-7】定義類的protected方法,通過創(chuàng)建對象來引用此方法。

classMax

{

privateintx,y;//定義私有變量

protectedintplay(ints,intt)//定義protected方法{intm;x=s;y=t;m=(x>y)?x/y:y/x;returnm;}}publicclassGetNum{publicstaticvoidmain(Stringargs[]){

intresult;

Maxss=newMax();

result=ss.play(5,45);

System.out.println(″result=″+result);

}}

程序運行結(jié)果:

result=9

【程序解析】對play()方法設(shè)置的protected屬性在程序引用中可以像使用public修飾的權(quán)限方法一樣來引用。

friendly

如果在通常條件下,成員變量或方法名前都沒有設(shè)定如public、private等訪問權(quán)限關(guān)鍵字,則通常稱此成員變量或方法為friendly,這意味著這些成員變量或方法對于包內(nèi)的所有類而言它們是可以訪問的,但對于包外的類,則不能對它們進行訪問。

【例5-8】使用方法的默認(rèn)訪問權(quán)限來引用此方法。publicclassX1{X1(){//X1類構(gòu)造器System.out.println(″Thisisaconstruct″);}voiddoing(){System.out.println(″Couldyoutellme″);}}//將此文件保存為X1.javaimportX1;//引用X1類publicclassX2{staticvoidstore(){System.out.println(″Thisisastoreprocessing″);}publicstaticvoidmain(Stringargs[]){X1y=newX1();y.doing();store();}}程序運行結(jié)果:ThisisaconstructCouldyoutellmeThisisastoreprocessing

【程序解析】類X1與類X2在編譯后系統(tǒng)自動將它們放在一個包內(nèi)。對于X1類中的doing()方法而言,如果不進行訪問權(quán)限設(shè)定,則通過“importX1”方法引入,使得X1類對象y可以調(diào)用doing()方法,即“y.doing();”。但是如果在X1類中對doing()方法強加private訪問權(quán)限(如:privatevoiddoing();),則當(dāng)使用y對象調(diào)用doing()方法時,編譯會出現(xiàn)錯誤提示信息。

任務(wù)進階

【進階任務(wù)19】創(chuàng)建并應(yīng)用People類

設(shè)計過程:

(1)在“記事本”中輸入如下程序:

classPeople

{

floatheight,weight;

Stringhead,ear,hand,foot,mouth;

voidspeak(Strings)

{

System.out.println(s);}}publicclassPeopleDemo{publicstaticvoidmain(Stringargs[]){Peoplezhubajie,sunwukong;//聲明對象zhubajie=newPeople();//為對象分配內(nèi)存sunwukong=newPeople();zhubajie.height=1.80f;//對象給自己的變量賦值zhubajie.head="大頭";zhubajie.ear="一雙大耳朵";sunwukong.height=1.62f;//對象給自己的變量賦值sunwukong.weight=1000f;sunwukong.head="金發(fā)飄飄";System.out.println("zhubajie的身高:"+zhubajie.height);System.out.println("zhubajie的頭:"+zhubajie.head);System.out.println("sunwukong的重量:"+sunwukong.weight);System.out.println("sunwukong的頭:"+sunwukong.head);zhubajie.speak("俺老豬我想娶媳婦");//對象調(diào)用方法System.out.println("zhubajie現(xiàn)在的頭:"+zhubajie.head);sunwukong.speak("老孫我重1000斤,我想騙八戒背我");//對象調(diào)用方法System.out.println("sunwukong現(xiàn)在的頭:"+sunwukong.head);}}

(2)將文件保存在“D:\\myprogram”文件夾中,文件名為PeopleDemo.java。

(3)在“命令提示符”窗口內(nèi)的“D:\\myprogram”提示符下,輸入“javacPeopleDemo.java”命令,然后在新的命令行中,輸入“javaPeopleDemo”命令,運行字節(jié)碼程序,輸出程序的運行結(jié)果,如圖5-1-2所示。圖5-1-2

程序PeopleDemo的運行結(jié)果【進階任務(wù)20】創(chuàng)建并應(yīng)用梯形類設(shè)計過程:(1)在“記事本”中輸入如下程序:classLader//梯形類{floatShangDi,Gao;staticfloatXiaDi;Lader(floatx,floaty,floath)//構(gòu)造函數(shù){ShangDi=x;XiaDi=y;Gao=h;}floatGetXiaDi(){returnXiaDi;}//獲取下底voidSetXiaDi(floatb){XiaDi=b;}//修改下底floatGetShangDi(){returnShangDi;}//獲取上底voidSetShangDi(floatb){ShangDi=b;}//設(shè)置上底floatGetGao(){returnGao;}//獲取高voidSetGao(floatb){Gao=b;}//修改高publicfloatarea(){//求梯形的面積floatresult;result=(ShangDi+XiaDi)Gao/2;returnresult;}}publicclassLaderDemo{publicstaticvoidmain(Stringargs[]){//分別創(chuàng)建2個梯形類的對象laderOne和laderTwoLaderladerOne=newLader(3.0f,10.0f,20),laderTwo=newLader(2.0f,3.0f,10);laderOne.SetXiaDi(100);//通過對象操作類變量

System.out.println("laderOne的XiaDi:"+laderOne.GetXiaDi());

System.out.println("laderTwo的XiaDi:"+laderTwo.GetXiaDi());

laderOne.Gao=30;laderTwo.SetXiaDi(60);

System.out.println("laderOne的ShangDi:"+laderOne.GetShangDi());

System.out.println("laderOne的XiaDi:"+laderOne.GetXiaDi());

System.out.println("laderOne的Gao:"+laderOne.GetGao());

System.out.println("laderOne的面積:"+laderOne.area());

System.out.println("laderTwo的ShangDi:"+laderTwo.GetShangDi());

System.out.println("laderTwo的XiaDi:"+laderTwo.GetXiaDi());

System.out.println("laderTwo的Gao:"+laderTwo.GetGao());

System.out.println("laderTwo的面積:"+laderTwo.area());}}

(2)將文件保存在“D:\\myprogram”文件夾中,文件名為LaderDemo.java。

(3)在“命令提示符”窗口內(nèi)的“D:\\myprogram”提示符下,輸入“javacLaderDemo.java”命令,然后在新的命令行中,輸入“javaLaderDemo”命令,運行字節(jié)碼程序,輸出程序的運行結(jié)果,如圖5-1-3所示。圖5-1-3

程序LaderDemo的運行結(jié)果第三章624三、分支程序與循環(huán)程序設(shè)計休息一下,鞏固所學(xué)的知識5.2【任務(wù)10】設(shè)計本科生類和研究生類

任務(wù)描述:

編寫一個程序UseStudents,設(shè)計本科生類(Undergraduate)和研究生類(Graduate),兩個類都由學(xué)生類派生。在本科生類中增加屬性:選修專業(yè)(Specialty),在研究生類中增加屬性:研究方向(Studydirection)。并分別創(chuàng)建這幾個類的對象。通過該任務(wù)的學(xué)習(xí),可以初步了解類的繼承和多態(tài)的基本概念,并掌握類的繼承和類的多態(tài)的使用方法。

設(shè)計過程:

(1)在“記事本”中輸入如下程序:

classStudents{//下面是Students類的成員變量和方法

publicStringname;publicintage;publicStringdegree;publicStudents(Stringname1,intage1,Stringdegree1)//構(gòu)造方法用于初始化類{name=name1;age=age1;degree=degree1;}publicvoidsetName(Stringn){name=n;}//設(shè)置學(xué)生姓名publicvoidsetAge(inta){age=a;}//設(shè)置學(xué)生年齡

publicvoidsetDegree(Stringd){degree=d;}//設(shè)置學(xué)生的學(xué)位

publicStringgetName(){returnname;}//獲取學(xué)生姓名

publicintgetAge(){returnage;}//獲取學(xué)生成績

publicStringgetDegree(){returndegree;}//獲取學(xué)生學(xué)位

publicvoidshow()

{System.out.println("學(xué)生的姓名是:"+name);System.out.println("學(xué)生的年齡是:"+age);System.out.println("學(xué)生的學(xué)位是:"+degree+"\\n");}}classUndergraduateextendsStudents{

//下面是Undergraduate類的成員變量和方法,是Students父類的一個子類

publicStringSpecialty;//選修專業(yè)

publicUndergraduate(Stringname1,intage1,Stringdegree1,StringSpecialty1)

{//構(gòu)造方法用于初始化類

super(name1,age1,degree1);

Specialty=Specialty1;

}

publicvoidsetSpecialty(Strings){Specialty=s;}//設(shè)置學(xué)生的選修專業(yè)

publicStringgetSpecialty(){returnSpecialty;}//獲取選修專業(yè)

publicvoidshow()

{System.out.println("學(xué)生的姓名是:"+name);System.out.println("學(xué)生的年齡是:"+age);System.out.println("學(xué)生的學(xué)位是:"+degree);System.out.println("學(xué)生的選修專業(yè)是:"+Specialty+"\\n");}}

classGraduateextendsStudents{

//下面是Graduate類的成員變量和方法,是Students父類的一個子類

publicStringStudydirection;//研究方向

publicGraduate(Stringname1,intage1,Stringdegree1,StringStudydirection1)

{//構(gòu)造方法用于初始化類

super(name1,age1,degree1);

Studydirection=Studydirection1;

}

publicvoidsetStudydirection(Strings){Studydirection=s;}//設(shè)置學(xué)生的研究方向

publicStringgetStudydirection(){returnStudydirection;}//獲取研究方向

publicvoidshow()

{

System.out.println("學(xué)生的姓名是:"+name);

System.out.println("學(xué)生的年齡是:"+age);

System.out.println("學(xué)生的學(xué)位是:"+degree);

System.out.println("學(xué)生的研究方向是:"+Studydirection+"\\n");}}

publicclassUseStudents{

publicstaticvoidmain(Stringargs[]){

Studentss1=newStudents("張三",18,"大專");

Undergraduates2=newUndergraduate("李四",20,"本科","學(xué)士");

Graduates3=newGraduate("王五",28,"碩士","Java程序設(shè)計");

s1.show();

s2.show();

s3.show();}}

(2)將文件保存在“D:\\myprogram”文件夾中,文件名為UseStudents.java。

(3)在“命令提示符”窗口內(nèi)的“D:\\myprogram”提示符下,輸入“javacUseStudents.java”命令,然后在新的命令行中,輸入“javaUseStudents”命令,運行字節(jié)碼程序,輸出程序的運行結(jié)果,如圖5-2-1所示。圖5-2-1

程序UseStudents的運行結(jié)果

相關(guān)知識

5.2.1類的繼承

繼承是面向?qū)ο蟪绦蛟O(shè)計的一個重要特征,它是通過繼承原有類的基礎(chǔ),派生出新類,進而開發(fā)出更為復(fù)雜的數(shù)據(jù)類型。新開發(fā)的對象既有新定義的行為特征,又包含有原有類定義的行為特征。

繼承的概念

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論